/// <summary>
 /// Locks the screen and demands authentication when a new keyboard is introduced to the system.
 /// </summary>
 private static void New_Keyboard(object sender, RawKeyboardEventArgs e)
 {
     if (e.keyboardCount > numberOfKeyboards)
     {
         DataSet dsValidKeyboards = KeyboardList.readKeyboardList(Configuration.profilePath);
         for (int j = 0; j < dsValidKeyboards.Tables[0].Rows.Count; j++)
         {
             if (dsValidKeyboards.Tables[0].Rows[j].ItemArray[0].Equals(e.deviceName.Substring(8, 17)))
             {
                 matchFound = true;
                 break;
             }
         }
         if (matchFound == true)
         {
             if (!alreadyLocked)
             {
                 alreadyLocked = true;
                 Lock("NewKeyboard", "");
                 alreadyLocked = false;
             }
         }
         else
         {
             if (!alreadyLocked)
             {
                 alreadyLocked = true;
                 Lock("NewKeyboard", "");
                 alreadyLocked = false;
             }
             dsValidKeyboards.Tables[0].Rows.Add(e.deviceName.Substring(8, 17));
             KeyboardList.SaveKeyboardList(dsValidKeyboards, Configuration.profilePath);
         }
     }
 }
        public void EnumerateDevices()
        {
            lock (_padLock)
            {
                _deviceList.Clear();

                var keyboardNumber = 0;

                var globalDevice = new KeyPressEvent
                {
                    DeviceName = "Global Keyboard",
                    DeviceHandle = IntPtr.Zero,
                    DeviceType = Win32.GetDeviceType(DeviceType.RimTypekeyboard),
                    Name = "Fake Keyboard. Some keys (ZOOM, MUTE, VOLUMEUP, VOLUMEDOWN) are sent to rawinput with a handle of zero.",
                    Source = keyboardNumber++.ToString(CultureInfo.InvariantCulture)
                };

                _deviceList.Add(globalDevice.DeviceHandle, globalDevice);

                var numberOfDevices = 0;
                uint deviceCount = 0;
                var dwSize = (Marshal.SizeOf(typeof(Rawinputdevicelist)));
                if (Win32.GetRawInputDeviceList(IntPtr.Zero, ref deviceCount, (uint)dwSize) == 0)
                {
                    var pRawInputDeviceList = Marshal.AllocHGlobal((int)(dwSize * deviceCount));
                    Win32.GetRawInputDeviceList(pRawInputDeviceList, ref deviceCount, (uint)dwSize);

                    for (var i = 0; i < deviceCount; i++)
                    {
                        uint pcbSize = 0;

                        // On Window 8 64bit when compiling against .Net > 3.5 using .ToInt32 you will generate an arithmetic overflow. Leave as it is for 32bit/64bit applications
                        var rid = (Rawinputdevicelist)Marshal.PtrToStructure(new IntPtr((pRawInputDeviceList.ToInt64() + (dwSize * i))), typeof(Rawinputdevicelist));

                        Win32.GetRawInputDeviceInfo(rid.hDevice, RawInputDeviceInfo.RIDI_DEVICENAME, IntPtr.Zero, ref pcbSize);

                        if (pcbSize <= 0) continue;

                        var pData = Marshal.AllocHGlobal((int)pcbSize);
                        Win32.GetRawInputDeviceInfo(rid.hDevice, RawInputDeviceInfo.RIDI_DEVICENAME, pData, ref pcbSize);
                        var deviceName = Marshal.PtrToStringAnsi(pData);

                        if (rid.dwType == DeviceType.RimTypekeyboard || rid.dwType == DeviceType.RimTypeHid)
                        {
                            var deviceDesc = Win32.GetDeviceDescription(deviceName);

                            var dInfo = new KeyPressEvent
                            {
                                DeviceName = Marshal.PtrToStringAnsi(pData),
                                DeviceHandle = rid.hDevice,
                                DeviceType = Win32.GetDeviceType(rid.dwType),
                                Name = deviceDesc,
                                Source = keyboardNumber++.ToString(CultureInfo.InvariantCulture)
                            };

                            if (!_deviceList.ContainsKey(rid.hDevice))
                            {
                                numberOfDevices++;
                                RawKeyboardEventArgs args = new RawKeyboardEventArgs();
                                args.deviceName = dInfo.DeviceName;
                                args.keyboardCount = numberOfDevices;
                                if (NewKeyboard != null)
                                    NewKeyboard(null, args);

                                _deviceList.Add(rid.hDevice, dInfo);

                            }

                        }

                        Marshal.FreeHGlobal(pData);
                    }

                    Marshal.FreeHGlobal(pRawInputDeviceList);

                    NumberOfKeyboards = numberOfDevices;
                    Debug.WriteLine("EnumerateDevices() found {0} Keyboard(s)", NumberOfKeyboards);
                    return;
                }
            }

            throw new Win32Exception(Marshal.GetLastWin32Error());
        }