internal static MouseModification FromBuffer(byte[] buffer)
        {
            MouseModification modifyRequest = new MouseModification();
            int bytesRead     = 0;
            int bytesRemained = buffer.Length;

            if (bytesRemained >= sizeof(ushort))
            {
                modifyRequest.ModifyCount = BitConverter.ToUInt16(buffer, bytesRead);
                bytesRead     += sizeof(ushort);
                bytesRemained -= sizeof(ushort);
                if (bytesRemained >= modifyRequest.ModifyCount * 2 * sizeof(ushort))
                {
                    modifyRequest.ModifyData = new ButtonModifyData[modifyRequest.ModifyCount];
                    for (int i = 0; i < modifyRequest.ModifyCount; i++)
                    {
                        modifyRequest.ModifyData[i].FromState = (MouseButtonState)BitConverter.ToUInt16(buffer, bytesRead);
                        bytesRead += sizeof(ushort);
                        modifyRequest.ModifyData[i].ToState = (MouseButtonState)BitConverter.ToUInt16(buffer, bytesRead);
                        bytesRead += sizeof(ushort);
                    }
                }
            }

            return(modifyRequest);
        }
        /// <summary>
        /// Sets the button modifications for the currently active device.
        /// </summary>
        /// <param name="modifyRequest">Structure that contains the key modification data.</param>
        public void MouseSetModification(MouseModification modifyRequest)
        {
            modifyRequest.RemoveRedundant();

            if (modifyRequest.ModifyData == null || modifyRequest.ModifyData.Length == 0)
            {
                ushort modifyCount = 0;
                if (!DeviceIoControl(_driverHandle, IOCTL_MOUSE_SET_MODIFY, ref modifyCount, sizeof(ushort), IntPtr.Zero, 0, out uint bytesReturned, IntPtr.Zero))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            else
            {
                var request = modifyRequest.GetBytes();
                if (!DeviceIoControl(_driverHandle, IOCTL_MOUSE_SET_MODIFY, request, (uint)request.Length, IntPtr.Zero, 0, out uint bytesReturned, IntPtr.Zero))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
        }
        /// <summary>
        /// Gets the button modification info of the currently active device.
        /// </summary>
        /// <returns></returns>
        public MouseModification MouseGetModifications()
        {
            MouseModification modifyRequest = new MouseModification();

            if (!DeviceIoControl(_driverHandle, IOCTL_MOUSE_GET_MODIFY, IntPtr.Zero, 0, out ushort modifyCount, sizeof(ushort), out uint bytesReturned, IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            modifyRequest.ModifyCount = modifyCount;
            if (modifyRequest.ModifyCount > 0)
            {
                int    outputSize   = sizeof(ushort) + modifyRequest.ModifyCount * Marshal.SizeOf(typeof(ButtonModifyData));
                byte[] outputBuffer = new byte[outputSize];
                if (!DeviceIoControl(_driverHandle, IOCTL_MOUSE_GET_MODIFY, IntPtr.Zero, 0, outputBuffer, (uint)outputSize, out bytesReturned, IntPtr.Zero))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                modifyRequest = MouseModification.FromBuffer(outputBuffer);
            }
            return(modifyRequest);
        }