public override async Task <HtmlXpathParserExitCode> RunParserAsync()
        {
            lastLastUrl = this.lastUrl;

            HtmlXpathParserExitCode exitCode = await base.RunParserAsync();

            if (!string.IsNullOrEmpty(lastLastUrl) && lastLastUrl.Equals(this.lastUrl))
            {
                Logging.Debug(LogOptions.ClassName, "The browser was not run, no need to cleanup");
            }
            else
            {
                Logging.Debug(LogOptions.ClassName, "The browser was run, needs to be cleanup");
                if (Browser != null)
                {
                    Browser.Navigated         -= Browser_Navigated;
                    Browser.DocumentCompleted -= Browser_DocumentCompleted;
                }
                hooked = false;
                WindowsInterop.SecurityAlertDialogWillBeShown -= this.WindowsInterop_SecurityAlertDialogWillBeShown;
                WindowsInterop.Unhook();

                if (ThreadMode)
                {
                    CleanupBrowser();
                }
            }

            return(exitCode);
        }
Beispiel #2
0
        public static void WriteAllBytes(string fileName, byte[] data)
        {
            using (var file = WindowsInterop.CreateFile(
                       fileName.ToLongPath(),
                       dwDesiredAccess: WindowsInterop.AccessMask.Write,
                       dwShareMode: 0,
                       lpSecurityAttributes: IntPtr.Zero,
                       dwCreationDisposition: WindowsInterop.CreateAttributes.CreateAlways,
                       dwFlagsAndAttributes: FileAttributes.Normal,
                       hTemplateFile: IntPtr.Zero))
            {
                if (file.IsInvalid)
                {
                    var innerException = new Win32Exception(Marshal.GetLastWin32Error());
                    throw new IOException("Failed to create or open file '" + fileName + "'.\n" + innerException.Message, innerException);
                }

                uint bytesWritten = 0;
                if (!WindowsInterop.WriteFile(file, data, (uint)data.Length, out bytesWritten, IntPtr.Zero))
                {
                    var innerException = new Win32Exception(Marshal.GetLastWin32Error());
                    throw new IOException("Failed to write to file '" + fileName + "'.\n" + innerException.Message, innerException);
                }
            }
        }
Beispiel #3
0
        static IntPtr RegisterForDeviceNotifications(IntPtr parent)
        {
            var usbNotifyHandle = IntPtr.Zero;
            var bdi             = new BroadcastDeviceInterface();

            bdi.DbccSize            = Marshal.SizeOf(bdi);
            bdi.BroadcastDeviceType = BroadcastDeviceType.DBT_DEVTYP_DEVICEINTERFACE;
            bdi.DbccClassguid       = DeviceInterfaceHid;

            var mem = IntPtr.Zero;

            try
            {
                mem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BroadcastDeviceInterface)));
                Marshal.StructureToPtr(bdi, mem, false);
                usbNotifyHandle = WindowsInterop.RegisterDeviceNotification(parent, mem, DeviceNotification.DEVICE_NOTIFY_WINDOW_HANDLE);
            }
            catch (Exception e)
            {
                Debug.WriteLine($"RawInput: Registration for device notifications Failed. Error: { Marshal.GetLastWin32Error() }");
                Debug.WriteLine(e.StackTrace);
            }
            finally
            {
                Marshal.FreeHGlobal(mem);
            }

            if (usbNotifyHandle == IntPtr.Zero)
            {
                Debug.WriteLine($"RawInput: Registration for device notifications Failed. Error: { Marshal.GetLastWin32Error() }");
            }

            return(usbNotifyHandle);
        }
Beispiel #4
0
        public static string ReadLocalRegKey(string keyPath, string valueName)
        {
            var platform = UMPSettings.RuntimePlatform;
            var value    = string.Empty;

            if (platform == UMPSettings.Platforms.Win)
            {
                var localMachine  = new UIntPtr(0x80000002u);
                var readKeyRights = 131097;
                var hKey          = UIntPtr.Zero;

                if (WindowsInterop.RegOpenKeyEx(localMachine, keyPath, 0, readKeyRights, out hKey) == 0)
                {
                    uint type;
                    uint size      = 1024;
                    var  keyBuffer = new StringBuilder((int)size);

                    if (WindowsInterop.RegQueryValueEx(hKey, valueName, 0, out type, keyBuffer, ref size) == 0)
                    {
                        value = keyBuffer.ToString();
                    }
                    else
                    {
                        Debug.LogWarning(string.Format("[ReadLocalRegKey] Can't read local reg key value: '{0}'", valueName));
                    }

                    WindowsInterop.RegCloseKey(hKey);
                }
                //else
                //    Debug.LogWarning(string.Format("[ReadLocalRegKey] Can't open local reg key: '{0}'", keyPath));
            }

            return(value);
        }
Beispiel #5
0
        private static bool SetLibraryDirectory(string path)
        {
            var supportedPlatform = UMPSettings.RuntimePlatform;

            if (supportedPlatform == UMPSettings.Platforms.Win)
            {
                return(WindowsInterop.SetDllDirectory(path));
            }

            if (supportedPlatform == UMPSettings.Platforms.Mac)
            {
                var pluginPath = Directory.GetParent(path.TrimEnd(Path.DirectorySeparatorChar)).FullName;
                pluginPath = Path.Combine(pluginPath, "plugins");

                if (Directory.Exists(pluginPath))
                {
                    Environment.SetEnvironmentVariable(VLC_EXT_ENV, pluginPath);
                    return(true);
                }
            }

            if (supportedPlatform == UMPSettings.Platforms.Linux)
            {
                Environment.SetEnvironmentVariable(VLC_EXT_ENV, path);
                Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", path);
                return(true);
            }

            return(false);
        }
Beispiel #6
0
        static public bool InternalLoadLibCefDll(string fullpath)
        {
            uint   LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
            IntPtr hr = WindowsInterop.LoadLibraryEx(fullpath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);

            if (hr == IntPtr.Zero)
            {
                return(false);
            }

            WriteDebugLine("libcef.dll Load OK ");


            if (PrintDebugInformation)
            {
                string verstr = LibCefInterop.CefVersionArrFromLibCefDll();
                WriteDebugLine("cef_version_info : " + verstr);
                if (verstr != LibCefInterop.CefVersionArr)
                {
                    WriteDebugLine(" * WARNING * , version not match for " + LibCefInterop.CefVersionArr);
                }
            }

            _libcefEverLoaded = true;
            _ApplyOptionsAfterLibCefLoaded();
            return(true);
        }
 protected void LockMemory(IntPtr pointer, ulong length)
 {
     if (!WindowsInterop.VirtualLock(pointer, (UIntPtr)length))
     {
         var errno = Marshal.GetLastWin32Error();
         throw new WindowsOperationFailedException("VirtualLock", 0L, errno);
     }
 }
Beispiel #8
0
 public static void DeleteFile(string fileName)
 {
     if (!WindowsInterop.DeleteFile(fileName.ToLongPath()))
     {
         var innerException = new Win32Exception(Marshal.GetLastWin32Error());
         throw new IOException("Failed to delete file '" + fileName + "'.\n" + innerException.Message, innerException);
     }
 }
Beispiel #9
0
 public static void SetFileAttributes(string path, FileAttributes fileAttributes)
 {
     if (!WindowsInterop.SetFileAttributes(path.ToLongPath(), fileAttributes))
     {
         var innerException = new Win32Exception(Marshal.GetLastWin32Error());
         throw new IOException("Failed to set file attributes on '" + path + "'.\n" + innerException.Message, innerException);
     }
 }
        public override void Free(IntPtr pointer, ulong length)
        {
            WindowsInterop.ZeroMemory(pointer, (UIntPtr)length);

            if (!WindowsInterop.VirtualFree(pointer, UIntPtr.Zero, AllocationType.RELEASE))
            {
                var errno = Marshal.GetLastWin32Error();
                throw new WindowsOperationFailedException("VirtualFree", 0L, errno);
            }
        }
Beispiel #11
0
 private void Host_SizeChanged()
 {
     WindowsInterop.SetWindowPos(
         _process.MainWindowHandle, IntPtr.Zero,
         -FrameSides, -FrameTop,
         _hostPanel.Width + 2 * FrameSides,
         _hostPanel.Height + FrameSides + FrameTop,
         WindowsInterop.SWP_NOACTIVATE | WindowsInterop.SWP_SHOWWINDOW);
     ZIndexFix();
 }
Beispiel #12
0
        public static bool FileExists(string path)
        {
            var attrib = WindowsInterop.GetFileAttributes(path.ToLongPath());

            if (attrib == -1)
            {
                return(false);
            }

            return(((FileAttributes)attrib).HasFlag(FileAttributes.Directory) == false);
        }
Beispiel #13
0
        public static void ShowFullscreen()
        {
            ShowWindow();

#if UNITY_EDITOR_WIN
            // Unity does not provide an API to maximize a floating utility window, so
            // go directly to Win32 to do the work.
            IntPtr hwnd = WindowsInterop.GetForegroundWindow();
            WindowsInterop.ShowWindow(hwnd, WindowsInterop.SW_SHOWMAXIMIZED);
#endif
        }
Beispiel #14
0
            protected override void OnResize(EventArgs e)
            {
                base.OnResize(e);

                if (hostWindowHandle != IntPtr.Zero)
                {
                    var rect = this.ClientRectangle;

                    WindowsInterop.SetWindowPos(hostWindowHandle, IntPtr.Zero, rect.Left, rect.Top, rect.Width, rect.Height, 0);
                }
            }
        public void SetReadWriteAccess(IntPtr pointer, ulong length)
        {
            length = AdjustLength(length);

            LockMemory(pointer, length);

            if (!WindowsInterop.CryptUnprotectMemory(pointer, (UIntPtr)length, CryptProtectMemoryOptions.SAME_PROCESS))
            {
                var errno = Marshal.GetLastWin32Error();
                throw new WindowsOperationFailedException("CryptUnprotectMemory", 0L, errno);
            }
        }
Beispiel #16
0
        public void OnResize(System.Drawing.Rectangle rect)
        {
            if (BrowserHost == null)
            {
                return;
            }

            uint SWP_NOOWNERZORDER = 0x0200;
            uint SWP_NOZORDER      = 0x0004;

            WindowsInterop.SetWindowPos(hostWindowHandle, IntPtr.Zero, rect.Left, rect.Top, rect.Width, rect.Height, SWP_NOOWNERZORDER | SWP_NOZORDER);
        }
        protected void UnlockMemory(IntPtr pointer, ulong length)
        {
            if (!WindowsInterop.VirtualUnlock(pointer, (UIntPtr)length))
            {
                var errno = Marshal.GetLastWin32Error();
                if (errno == (int)VirtualUnlockErrors.ERROR_NOT_LOCKED)
                {
                    return;
                }

                throw new WindowsOperationFailedException("VirtualUnlock", 0L, errno);
            }
        }
Beispiel #18
0
        public static IntPtr LoadLibrary(string libName, string libraryPath)
        {
            var libHandler     = IntPtr.Zero;
            var libNameWithExt = string.Empty;

            if (string.IsNullOrEmpty(libName) || string.IsNullOrEmpty(libraryPath))
            {
                return(libHandler);
            }

            SetLibraryDirectory(libraryPath);

            var libraryFiles = Directory.GetFiles(libraryPath);

            foreach (var libraryFile in libraryFiles)
            {
                if (libraryFile.EndsWith(".meta"))
                {
                    continue;
                }

                var fileName = Path.GetFileName(libraryFile);

                if (fileName.StartsWith(libName + ".") && (string.IsNullOrEmpty(libNameWithExt) || fileName.Any(char.IsDigit)))
                {
                    libNameWithExt = fileName;
                }
            }

            switch (UMPSettings.RuntimePlatform)
            {
            case UMPSettings.Platforms.Win:
                libHandler = WindowsInterop.LoadLibrary(Path.Combine(libraryPath, libNameWithExt));
                break;

            case UMPSettings.Platforms.Mac:
                libHandler = MacInterop.dlopen(Path.Combine(libraryPath, libNameWithExt), LIN_RTLD_NOW);
                break;

            case UMPSettings.Platforms.Linux:
                libHandler = LinuxInterop.dlopen(Path.Combine(libraryPath, libNameWithExt), LIN_RTLD_NOW);
                break;
            }

            if (libHandler == IntPtr.Zero)
            {
                throw new Exception(string.Format("[LoadLibrary] Can't load '{0}' library", libName));
            }

            return(libHandler);
        }
Beispiel #19
0
        public static void CreateDirectory(string pathName)
        {
            if (!WindowsInterop.CreateDirectory(pathName.ToLongPath(), IntPtr.Zero))
            {
                var errorCode = Marshal.GetLastWin32Error();
                if (errorCode == 0xB7 /* Already exists */)
                {
                    return;
                }

                var innerException = new Win32Exception(errorCode);
                throw new IOException("Failed to create directory '" + pathName + "'.\n" + innerException.Message, innerException);
            }
        }
        public override IntPtr Alloc(ulong length)
        {
            length = AdjustLength(length);

            var result = WindowsInterop.VirtualAlloc(IntPtr.Zero, (UIntPtr)length, AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.PAGE_EXECUTE_READWRITE);

            if (result == IntPtr.Zero || result == InvalidPointer)
            {
                var errno = Marshal.GetLastWin32Error();
                throw new WindowsOperationFailedException("VirtualAlloc", (long)result, errno);
            }

            return(result);
        }
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(LaunchProfiles) ||
                string.IsNullOrEmpty(UserFile))
            {
                Debug.Fail("Should have gotten something to monitor");
                return(true);
            }

            try
            {
                if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
                {
                    var maxAttempts = 5;
                    for (var i = 1; i <= maxAttempts; i++)
                    {
                        if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
                        {
                            BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor),
                                                            new ActiveDocumentMonitor(LaunchProfiles !, UserFile !,
                                                                                      StartupFiles.Select(x => x.ItemSpec).ToArray(), services),
                                                            RegisteredTaskObjectLifetime.AppDomain, false);

                            return(true);
                        }
                        else
                        {
                            try
                            {
                                BuildEngine4.Yield();
                            }
                            catch (Exception e)
                            {
                                Debug.WriteLine(e);
                            }
                            // Increase the wait time to allow more time between retries
                            Thread.Sleep(200 * i);
                        }
                    }

                    Debug.Fail("Failed to get IServiceProvider to monitor for active document.");
                }
                else
                {
                    // NOTE: this means we only support ONE project/launchProfiles per IDE.
                    monitor.Refresh(LaunchProfiles !, UserFile !,
                                    StartupFiles.Select(x => x.ItemSpec).ToArray());
                }
            }
Beispiel #22
0
        public static T GetLibraryDelegate <T>(IntPtr handler)
        {
            string functionName      = null;
            var    procAddress       = IntPtr.Zero;
            var    supportedPlatform = UMPSettings.RuntimePlatform;

            try
            {
                var attrs = typeof(T).GetCustomAttributes(typeof(NativeFunctionAttribute), false);
                if (attrs.Length == 0)
                {
                    throw new Exception("[GetLibraryDelegate] Could not find the native attribute type.");
                }

                var attr = (NativeFunctionAttribute)attrs[0];
                functionName = attr.FunctionName;
                if (_interopDelegates.ContainsKey(functionName))
                {
                    return((T)Convert.ChangeType(_interopDelegates[attr.FunctionName], typeof(T), null));
                }

                if (supportedPlatform == UMPSettings.Platforms.Win)
                {
                    procAddress = WindowsInterop.GetProcAddress(handler, attr.FunctionName);
                }
                if (supportedPlatform == UMPSettings.Platforms.Mac)
                {
                    procAddress = MacInterop.dlsym(handler, attr.FunctionName);
                }
                if (supportedPlatform == UMPSettings.Platforms.Linux)
                {
                    procAddress = LinuxInterop.dlsym(handler, attr.FunctionName);
                }

                if (procAddress == IntPtr.Zero)
                {
                    throw new Exception(string.Format("[GetLibraryDelegate] Can't get process address from '{0}'", handler));
                }

                var delegateForFunctionPointer = Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
                _interopDelegates[attr.FunctionName] = delegateForFunctionPointer;
                return((T)Convert.ChangeType(delegateForFunctionPointer, typeof(T), null));
            }
            catch (Exception e)
            {
                throw new MissingMethodException(string.Format("[GetLibraryDelegate] The address of the function '{0}' does not exist in '{1}' library.", functionName, handler), e);
            }
        }
Beispiel #23
0
        public static bool FreeLibrary(IntPtr handler)
        {
            switch (UMPSettings.RuntimePlatform)
            {
            case UMPSettings.Platforms.Win:
                return(WindowsInterop.FreeLibrary(handler));

            case UMPSettings.Platforms.Mac:
                return(MacInterop.dlclose(handler) == 0);

            case UMPSettings.Platforms.Linux:
                return(LinuxInterop.dlclose(handler) == 0);
            }

            return(false);
        }
Beispiel #24
0
        private void BackgroundForm_Load(object sender, EventArgs e)
        {
            HandleDeviceContext = GetDC(BackgroundForm.Handle);

            _xDpi = GetDeviceCaps(HandleDeviceContext, (int)DeviceCap.LOGPIXELSX);
            _yDpi = GetDeviceCaps(HandleDeviceContext, (int)DeviceCap.LOGPIXELSY);

            // 96 is the default dpi for windows
            // https://docs.microsoft.com/en-us/windows/desktop/directwrite/how-to-ensure-that-your-application-displays-properly-on-high-dpi-displays
            var width  = _xDpi * Screen.Bounds.Width / 96f;
            var height = _yDpi * Screen.Bounds.Height / 96f;

            WindowsInterop.SetWinFullScreen(BackgroundForm.Handle, Screen.Bounds.Left, Screen.Bounds.Top, (int)width, (int)height);

            Log.Information("Blank screen resized {device} {bounds} xDpi {xDpi} yDpi {yDpi}", Screen.DeviceName, Screen.Bounds, _xDpi, _yDpi);
        }
        public WindowsProtectedMemoryAllocatorVirtualAlloc(IConfiguration configuration)
        {
            UIntPtr min      = UIntPtr.Zero;
            UIntPtr max      = UIntPtr.Zero;
            IntPtr  hProcess = WindowsInterop.GetCurrentProcess();
            var     result   = WindowsInterop.GetProcessWorkingSetSize(hProcess, ref min, ref max);

            if (!result)
            {
                throw new Exception("GetProcessWorkingSetSize failed");
            }

            var minConfig = configuration["minimumWorkingSetSize"];

            if (!string.IsNullOrWhiteSpace(minConfig))
            {
                min = new UIntPtr(ulong.Parse(minConfig));
            }
            else
            {
                if (min.ToUInt64() < DefaultMinimumWorkingSetSize)
                {
                    min = new UIntPtr(DefaultMinimumWorkingSetSize);
                }
            }

            var maxConfig = configuration["maximumWorkingSetSize"];

            if (!string.IsNullOrWhiteSpace(maxConfig))
            {
                max = new UIntPtr(ulong.Parse(maxConfig));
            }
            else
            {
                if (max.ToUInt64() < DefaultMaximumWorkingSetSize)
                {
                    max = new UIntPtr(DefaultMaximumWorkingSetSize);
                }
            }

            result = WindowsInterop.SetProcessWorkingSetSize(hProcess, min, max);
            if (!result)
            {
                throw new Exception($"SetProcessWorkingSetSize({min.ToUInt64()},{max.ToUInt64()}) failed");
            }
        }
        public Game(int width, int height, string title) : base(width, height, GraphicsMode.Default, title)
        {
            IntPtr initialStyle = WindowsInterop.GetWindowLongPtr(new HandleRef(this, this.WindowInfo.Handle), -20);

            const int WS_EX_LAYERED     = 0x00080000;
            const int WS_EX_TRANSPARENT = 0x00000020;
            const int WS_EX_TOPMOST     = 0x00000008;

            if (WindowsInterop.SetWindowLongPtr(new HandleRef(this, this.WindowInfo.Handle), -20, new IntPtr(initialStyle.ToInt32() | WS_EX_TRANSPARENT | WS_EX_LAYERED)) == IntPtr.Zero)
            {
                Console.WriteLine("failure");
            }
            if (WindowsInterop.SetLayeredWindowAttributes(this.WindowInfo.Handle, 0x000000FF, 255, 0x00000001 | 0x00000002) == false)
            {
                Console.WriteLine("setting failure");
            }

            WindowsInterop.SetWindowPos(this.WindowInfo.Handle, HWND_TOPMOST, this.X, this.Y, this.Width, this.Height, SWP.NOSIZE);
            this.WindowBorder = WindowBorder.Hidden;
        }
        public override bool Execute()
        {
            if (FlagFile == null || StartupFile == null)
            {
                return(true);
            }

            if (!File.Exists(FlagFile) ||
                File.ReadAllText(FlagFile) != StartupFile)
            {
                // This defers the opening until the build completes.
                BuildEngine4.RegisterTaskObject(
                    StartupFile,
                    new DisposableAction(() => WindowsInterop.EnsureOpened(StartupFile)),
                    RegisteredTaskObjectLifetime.Build, false);

                File.WriteAllText(FlagFile, StartupFile);
            }

            return(true);
        }
        public override void Cancel()
        {
            base.Cancel();

            if (ThreadMode && browserDispatcher != null)
            {
                if (Browser != null)
                {
                    Browser.Navigated         -= Browser_Navigated;
                    Browser.DocumentCompleted -= Browser_DocumentCompleted;
                }

                if (hooked)
                {
                    WindowsInterop.SecurityAlertDialogWillBeShown -= this.WindowsInterop_SecurityAlertDialogWillBeShown;
                    WindowsInterop.Unhook();
                }

                CleanupBrowser();
            }
        }
Beispiel #29
0
        private FrameworkElement CreateHostedProcess()
        {
            _hostPanel = new Forms.Panel();

            var psi = new ProcessStartInfo();

            PrepareProcess(psi);

            psi.FileName       = GetProcessName();
            psi.Arguments      = GetProcessArguments();
            psi.WindowStyle    = ProcessWindowStyle.Maximized;
            psi.CreateNoWindow = false;

            _process = Process.Start(psi);
            _process.EnableRaisingEvents = true;
            _process.Exited   += Process_Exited;
            _process.Disposed += Process_Disposed;

            WaitForProcess(_process);

            WindowsInterop.SetParent(_process.MainWindowHandle, _hostPanel.Handle);
            WindowsInterop.SetWindowPos(
                _process.MainWindowHandle, IntPtr.Zero,
                -FrameSides, -FrameTop,
                _hostPanel.Width + 2 * FrameSides,
                _hostPanel.Height + FrameSides + FrameTop,
                WindowsInterop.SWP_NOACTIVATE | WindowsInterop.SWP_SHOWWINDOW);
            ZIndexFix();

            _hostGrid = new Grid();
            _hostGrid.Children.Add(new WindowsFormsHost {
                Child = _hostPanel
            });

            Observable
            .FromEventPattern <SizeChangedEventArgs>(_hostGrid, "SizeChanged")
            .Subscribe(x => _hostGrid?.Dispatcher.Invoke(Host_SizeChanged));

            return(_hostGrid);
        }
Beispiel #30
0
        protected override void WndProc(ref Message message)
        {
            switch (message.Msg)
            {
            case WindowsInterop.WM_INPUT:
            {
                var dwSize  = 0;
                var hdevice = message.LParam;
                WindowsInterop.GetRawInputData(hdevice, DataCommand.RID_INPUT, IntPtr.Zero, ref dwSize, Marshal.SizeOf(typeof(RawInputHeader)));
                if (dwSize != WindowsInterop.GetRawInputData(hdevice, DataCommand.RID_INPUT, out rawBuffer, ref dwSize, Marshal.SizeOf(typeof(RawInputHeader))))
                {
                    Debug.WriteLine("RawInput: Failed to get the buffer.");
                }
                else
                {
                    switch ((DeviceType)rawBuffer.header.dwType)
                    {
                    case DeviceType.Mouse:
                        OnMouseEvent();
                        break;

                    case DeviceType.Keyboard:
                        OnKeyboardEvent();
                        break;

                    case DeviceType.HID:
                        break;
                    }
                }
            }
            break;

            case WindowsInterop.WM_USB_DEVICECHANGE:
                Debug.WriteLine("RawInput: USB Device Arrival / Removal");
                // TODO: Refresh all devices and call device connect / disconnect events
                break;
            }

            base.WndProc(ref message);
        }