mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-19 07:01:35 +08:00
798355e342
新增反代脚本只对Steam内置浏览器生效的选项
587 lines
16 KiB
C#
587 lines
16 KiB
C#
/*
|
|
* Copyright (C) 2015 Colin Mackie.
|
|
* This software is distributed under the terms of the GNU General Public License.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
using Microsoft.Win32.SafeHandles;
|
|
|
|
namespace WinAuth
|
|
{
|
|
/// <summary>
|
|
/// Class that loads all current USB devices so we can find the YubiKey
|
|
/// Credit to http://brandonw.net/
|
|
/// </summary>
|
|
public class HIDDevice : IDisposable
|
|
{
|
|
#region P/Invoke
|
|
|
|
[Flags]
|
|
private enum EFileAttributes : uint
|
|
{
|
|
Readonly = 0x00000001,
|
|
Hidden = 0x00000002,
|
|
System = 0x00000004,
|
|
Directory = 0x00000010,
|
|
Archive = 0x00000020,
|
|
Device = 0x00000040,
|
|
Normal = 0x00000080,
|
|
Temporary = 0x00000100,
|
|
SparseFile = 0x00000200,
|
|
ReparsePoint = 0x00000400,
|
|
Compressed = 0x00000800,
|
|
Offline = 0x00001000,
|
|
NotContentIndexed = 0x00002000,
|
|
Encrypted = 0x00004000,
|
|
Write_Through = 0x80000000,
|
|
Overlapped = 0x40000000,
|
|
NoBuffering = 0x20000000,
|
|
RandomAccess = 0x10000000,
|
|
SequentialScan = 0x08000000,
|
|
DeleteOnClose = 0x04000000,
|
|
BackupSemantics = 0x02000000,
|
|
PosixSemantics = 0x01000000,
|
|
OpenReparsePoint = 0x00200000,
|
|
OpenNoRecall = 0x00100000,
|
|
FirstPipeInstance = 0x00080000
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct HIDD_ATTRIBUTES
|
|
{
|
|
public Int32 Size;
|
|
public Int16 VendorID;
|
|
public Int16 ProductID;
|
|
public Int16 VersionNumber;
|
|
}
|
|
|
|
//[StructLayout(LayoutKind.Sequential)]
|
|
//private struct GUID
|
|
//{
|
|
// public int Data1;
|
|
// public System.UInt16 Data2;
|
|
// public System.UInt16 Data3;
|
|
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
|
// public byte[] data4;
|
|
//}
|
|
|
|
[DllImport("hid.dll", SetLastError = true)]
|
|
private static extern void HidD_GetHidGuid(
|
|
ref Guid lpHidGuid);
|
|
|
|
[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
private static extern IntPtr SetupDiGetClassDevs(
|
|
ref Guid ClassGuid,
|
|
IntPtr Enumerator, //[MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
|
|
IntPtr hwndParent,
|
|
UInt32 Flags
|
|
);
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct SP_DEVICE_INTERFACE_DATA
|
|
{
|
|
public Int32 cbSize;
|
|
public Guid InterfaceClassGuid;
|
|
public Int32 Flags;
|
|
public UIntPtr Reserved;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
private struct SP_DEVICE_INTERFACE_DETAIL_DATA
|
|
{
|
|
public UInt32 cbSize;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
|
public string DevicePath;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
|
private struct PSP_DEVICE_INTERFACE_DETAIL_DATA
|
|
{
|
|
public Int32 cbSize;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
|
public string DevicePath;
|
|
}
|
|
|
|
[DllImport(@"setupapi.dll", SetLastError = true)]
|
|
private static extern Boolean SetupDiGetDeviceInterfaceDetail(
|
|
IntPtr hDevInfo,
|
|
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
|
|
IntPtr deviceInterfaceDetailData,
|
|
UInt32 deviceInterfaceDetailDataSize,
|
|
out UInt32 requiredSize,
|
|
IntPtr deviceInfoData
|
|
);
|
|
|
|
[DllImport(@"setupapi.dll", SetLastError = true)]
|
|
private static extern Boolean SetupDiGetDeviceInterfaceDetail(
|
|
IntPtr hDevInfo,
|
|
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
|
|
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
|
|
UInt32 deviceInterfaceDetailDataSize,
|
|
out UInt32 requiredSize,
|
|
IntPtr deviceInfoData
|
|
);
|
|
|
|
[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
private static extern Boolean SetupDiEnumDeviceInterfaces(
|
|
IntPtr hDevInfo,
|
|
//ref SP_DEVINFO_DATA devInfo,
|
|
IntPtr devInvo,
|
|
ref Guid interfaceClassGuid,
|
|
Int32 memberIndex,
|
|
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
|
|
);
|
|
|
|
[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
private static extern UInt16 SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);
|
|
|
|
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
static extern SafeFileHandle CreateFile(
|
|
string lpFileName,
|
|
UInt32 dwDesiredAccess,
|
|
UInt32 dwShareMode,
|
|
IntPtr lpSecurityAttributes,
|
|
UInt32 dwCreationDisposition,
|
|
UInt32 dwFlagsAndAttributes,
|
|
IntPtr hTemplateFile
|
|
);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
private static extern int CloseHandle(SafeFileHandle hObject);
|
|
[DllImport("kernel32.dll")]
|
|
private static extern int CloseHandle(IntPtr hObject);
|
|
|
|
[DllImport("hid.dll", SetLastError = true)]
|
|
private static extern int HidD_GetPreparsedData(
|
|
SafeFileHandle hObject,
|
|
ref IntPtr pPHIDP_PREPARSED_DATA);
|
|
|
|
[DllImport("hid.dll", SetLastError = true)]
|
|
private static extern int HidP_GetCaps(
|
|
IntPtr pPHIDP_PREPARSED_DATA,
|
|
ref HIDP_CAPS myPHIDP_CAPS);
|
|
|
|
[DllImport("hid.dll")]
|
|
internal extern static bool HidD_SetOutputReport(
|
|
IntPtr HidDeviceObject,
|
|
byte[] lpReportBuffer,
|
|
uint ReportBufferLength);
|
|
|
|
[DllImport("hid.dll")]
|
|
private static extern Boolean HidD_GetAttributes(IntPtr HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
private static extern int WriteFile(SafeFileHandle hFile, ref byte lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int lpOverlapped);
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct HIDP_CAPS
|
|
{
|
|
public UInt16 Usage;
|
|
public UInt16 UsagePage;
|
|
public UInt16 InputReportByteLength;
|
|
public UInt16 OutputReportByteLength;
|
|
public UInt16 FeatureReportByteLength;
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
|
|
public UInt16[] Reserved;
|
|
public UInt16 NumberLinkCollectionNodes;
|
|
public UInt16 NumberInputButtonCaps;
|
|
public UInt16 NumberInputValueCaps;
|
|
public UInt16 NumberInputDataIndices;
|
|
public UInt16 NumberOutputButtonCaps;
|
|
public UInt16 NumberOutputValueCaps;
|
|
public UInt16 NumberOutputDataIndices;
|
|
public UInt16 NumberFeatureButtonCaps;
|
|
public UInt16 NumberFeatureValueCaps;
|
|
public UInt16 NumberFeatureDataIndices;
|
|
}
|
|
|
|
private const int DIGCF_PRESENT = 0x00000002;
|
|
private const int DIGCF_DEVICEINTERFACE = 0x00000010;
|
|
private const int DIGCF_INTERFACEDEVICE = 0x00000010;
|
|
private const uint GENERIC_READ = 0x80000000;
|
|
private const uint GENERIC_WRITE = 0x40000000;
|
|
private const uint FILE_SHARE_READ = 0x00000001;
|
|
private const uint FILE_SHARE_WRITE = 0x00000002;
|
|
private const int OPEN_EXISTING = 3;
|
|
|
|
#endregion
|
|
|
|
#region Declarations
|
|
|
|
private bool _found = false;
|
|
private Guid _guid;
|
|
private IntPtr _hDeviceInfo = IntPtr.Zero;
|
|
private SP_DEVICE_INTERFACE_DATA _SP_DEVICE_INTERFACE_DATA;
|
|
private string _devicePath;
|
|
private SafeFileHandle _hidHandle;
|
|
private FileStream _stream;
|
|
|
|
#endregion
|
|
|
|
#region Public Events
|
|
|
|
public event EventHandler<HIDDeviceDataReceivedEventArgs> DataReceived;
|
|
|
|
#endregion
|
|
|
|
#region Constructors / Teardown
|
|
|
|
public HIDDevice(string devicePath)
|
|
{
|
|
_Init(devicePath, false);
|
|
}
|
|
|
|
public HIDDevice(int vendorId, int productId)
|
|
{
|
|
_Init(vendorId, productId, false);
|
|
}
|
|
|
|
public HIDDevice(int vendorId, int productId, bool throwNotFoundError)
|
|
{
|
|
_Init(vendorId, productId, throwNotFoundError);
|
|
}
|
|
|
|
public HIDDevice(string devicePath, bool throwNotFoundError)
|
|
{
|
|
_Init(devicePath, throwNotFoundError);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
public int InputReportLength { get; private set; }
|
|
public int OutputReportLength { get; private set; }
|
|
|
|
public bool Found
|
|
{
|
|
get
|
|
{
|
|
return _found;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
public class HIDDeviceEntry
|
|
{
|
|
public string Path { get; set; }
|
|
public int VendorID { get; set; }
|
|
public int ProductID { get; set; }
|
|
|
|
public HIDDeviceEntry(string path, int vid, int pid)
|
|
{
|
|
Path = path;
|
|
VendorID = vid;
|
|
ProductID = pid;
|
|
}
|
|
}
|
|
|
|
public static List<HIDDeviceEntry> GetAllDevices(int? vendorId = null, int? productId = null)
|
|
{
|
|
return GetAllDevices(new Guid(Guid.Empty.ToString()), vendorId, productId);
|
|
}
|
|
public static List<HIDDeviceEntry> GetAllDevices(Guid guid, int? vendorId = null, int? productId = null)
|
|
{
|
|
int index = 0;
|
|
//GUID guid = new GUID();
|
|
var devices = new List<HIDDeviceEntry>();
|
|
|
|
if (guid == Guid.Empty)
|
|
{
|
|
HidD_GetHidGuid(ref guid);
|
|
}
|
|
IntPtr devicesHandle = SetupDiGetClassDevs(ref guid, IntPtr.Zero, IntPtr.Zero, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT);
|
|
var diData = new SP_DEVICE_INTERFACE_DATA();
|
|
diData.cbSize = Marshal.SizeOf(diData);
|
|
|
|
while (SetupDiEnumDeviceInterfaces(devicesHandle, IntPtr.Zero, ref guid, index, ref diData))
|
|
{
|
|
//Get the buffer size
|
|
UInt32 size;
|
|
SetupDiGetDeviceInterfaceDetail(devicesHandle, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
|
|
|
|
// Uh...yeah.
|
|
var diDetail = new SP_DEVICE_INTERFACE_DETAIL_DATA();
|
|
diDetail.cbSize = (uint)(IntPtr.Size == 8 ? 8 : 5);
|
|
|
|
//Get detailed information
|
|
if (SetupDiGetDeviceInterfaceDetail(devicesHandle, ref diData, ref diDetail, size, out size, IntPtr.Zero))
|
|
{
|
|
//Get a handle to this device
|
|
var handle = CreateFile(diDetail.DevicePath, 4 /*GENERIC_WRITE*/, 3 /*FILE_SHARE_READ | FILE_SHARE_WRITE*/, IntPtr.Zero, 4 /*OPEN_EXISTING*/, 0, IntPtr.Zero);
|
|
if (handle.IsInvalid == false)
|
|
{
|
|
//Get this device's attributes
|
|
var attrib = new HIDD_ATTRIBUTES();
|
|
attrib.Size = Marshal.SizeOf(attrib);
|
|
if (HidD_GetAttributes(handle.DangerousGetHandle(), ref attrib))
|
|
{
|
|
int vid = attrib.VendorID & 0xFFFF;
|
|
int pid = attrib.ProductID & 0xFFFF;
|
|
//See if this is one we care about
|
|
if ((!vendorId.HasValue || vid == vendorId.Value) &&
|
|
(!productId.HasValue || pid == productId.Value))
|
|
{
|
|
devices.Add(new HIDDeviceEntry(diDetail.DevicePath, vid, pid));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Close the handle
|
|
handle.Close();
|
|
//CloseHandle(handle);
|
|
}
|
|
|
|
//Move on
|
|
index++;
|
|
}
|
|
|
|
SetupDiDestroyDeviceInfoList(devicesHandle);
|
|
|
|
return devices;
|
|
}
|
|
|
|
public static bool IsDetected(int vendorId, int productId)
|
|
{
|
|
var device = new HIDDevice(vendorId, productId, false);
|
|
bool ret = device.Found;
|
|
|
|
device.Dispose();
|
|
|
|
return ret;
|
|
}
|
|
|
|
public void Write(byte reportType, byte[] data)
|
|
{
|
|
int bytesSent = 0;
|
|
|
|
do
|
|
{
|
|
byte[] buffer = new byte[OutputReportLength];
|
|
buffer[0] = reportType;
|
|
for (int i = 1; i < buffer.Length; i++)
|
|
{
|
|
if (bytesSent < data.Length)
|
|
{
|
|
buffer[i] = data[bytesSent];
|
|
bytesSent++;
|
|
}
|
|
else
|
|
{
|
|
buffer[i] = 0;
|
|
}
|
|
}
|
|
|
|
HidD_SetOutputReport(_hidHandle.DangerousGetHandle(), buffer, (uint)buffer.Length);
|
|
} while (bytesSent < data.Length);
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
try
|
|
{
|
|
_stream.Close();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
CloseHandle(_hidHandle);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
SetupDiDestroyDeviceInfoList(_hDeviceInfo);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try
|
|
{
|
|
Disconnect();
|
|
}
|
|
catch
|
|
{
|
|
//Don't care...
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
|
|
private void _Init(int vendorId, int productId, bool throwNotFoundError)
|
|
{
|
|
var devices = HIDDevice.GetAllDevices(vendorId, productId);
|
|
|
|
if (devices != null && devices.Count > 0)
|
|
{
|
|
_Init(devices[0].Path, throwNotFoundError);
|
|
}
|
|
else
|
|
{
|
|
if (throwNotFoundError)
|
|
throw new InvalidOperationException("Device not found");
|
|
}
|
|
}
|
|
|
|
private void _Init(string devicePath, bool throwNotFoundError)
|
|
{
|
|
bool result;
|
|
int deviceCount = 0;
|
|
uint size;
|
|
uint requiredSize;
|
|
|
|
_guid = new Guid();
|
|
HidD_GetHidGuid(ref _guid);
|
|
|
|
_hDeviceInfo = SetupDiGetClassDevs(ref _guid, IntPtr.Zero, IntPtr.Zero, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT);
|
|
|
|
do
|
|
{
|
|
_SP_DEVICE_INTERFACE_DATA = new SP_DEVICE_INTERFACE_DATA();
|
|
_SP_DEVICE_INTERFACE_DATA.cbSize = Marshal.SizeOf(_SP_DEVICE_INTERFACE_DATA);
|
|
result = SetupDiEnumDeviceInterfaces(_hDeviceInfo, IntPtr.Zero, ref _guid, deviceCount, ref _SP_DEVICE_INTERFACE_DATA);
|
|
SetupDiGetDeviceInterfaceDetail(_hDeviceInfo, ref _SP_DEVICE_INTERFACE_DATA, IntPtr.Zero, 0, out requiredSize, IntPtr.Zero);
|
|
size = requiredSize;
|
|
var diDetail = new SP_DEVICE_INTERFACE_DETAIL_DATA();
|
|
diDetail.cbSize = (uint)(IntPtr.Size == 8 ? 8 : 5);
|
|
SetupDiGetDeviceInterfaceDetail(_hDeviceInfo, ref _SP_DEVICE_INTERFACE_DATA, ref diDetail,
|
|
size, out requiredSize, IntPtr.Zero);
|
|
_devicePath = diDetail.DevicePath;
|
|
|
|
if (_devicePath == devicePath)
|
|
{
|
|
_found = true;
|
|
_SP_DEVICE_INTERFACE_DATA = new SP_DEVICE_INTERFACE_DATA();
|
|
_SP_DEVICE_INTERFACE_DATA.cbSize = Marshal.SizeOf(_SP_DEVICE_INTERFACE_DATA);
|
|
SetupDiEnumDeviceInterfaces(_hDeviceInfo, IntPtr.Zero, ref _guid, deviceCount, ref _SP_DEVICE_INTERFACE_DATA);
|
|
size = 0;
|
|
requiredSize = 0;
|
|
SetupDiGetDeviceInterfaceDetail(_hDeviceInfo, ref _SP_DEVICE_INTERFACE_DATA, IntPtr.Zero, size, out requiredSize, IntPtr.Zero);
|
|
SetupDiGetDeviceInterfaceDetail(_hDeviceInfo, ref _SP_DEVICE_INTERFACE_DATA, IntPtr.Zero, size, out requiredSize, IntPtr.Zero);
|
|
_hidHandle = CreateFile(_devicePath, (uint)FileAccess.ReadWrite, (uint)FileShare.ReadWrite, IntPtr.Zero, (uint)FileMode.Open, (uint)EFileAttributes.Overlapped, IntPtr.Zero);
|
|
|
|
//Get report lengths
|
|
IntPtr preparsedDataPtr = (IntPtr)0xffffffff;
|
|
if (HidD_GetPreparsedData(_hidHandle, ref preparsedDataPtr) != 0)
|
|
{
|
|
var caps = new HIDP_CAPS();
|
|
HidP_GetCaps(preparsedDataPtr, ref caps);
|
|
OutputReportLength = caps.OutputReportByteLength;
|
|
InputReportLength = caps.InputReportByteLength;
|
|
|
|
_stream = new FileStream(_hidHandle, FileAccess.ReadWrite, InputReportLength, true);
|
|
var buffer = new byte[InputReportLength];
|
|
_stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(OnReadData), buffer);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
deviceCount++;
|
|
} while (result);
|
|
|
|
if (!_found)
|
|
{
|
|
if (throwNotFoundError)
|
|
throw new InvalidOperationException("Device not found");
|
|
}
|
|
}
|
|
|
|
private void OnReadData(IAsyncResult result)
|
|
{
|
|
var buffer = (byte[])result.AsyncState;
|
|
|
|
try
|
|
{
|
|
_stream.EndRead(result);
|
|
var receivedData = new byte[InputReportLength - 1];
|
|
Array.Copy(buffer, 1, receivedData, 0, receivedData.Length);
|
|
|
|
if (receivedData != null)
|
|
{
|
|
if (DataReceived != null)
|
|
{
|
|
DataReceived(this, new HIDDeviceDataReceivedEventArgs(buffer[0], receivedData));
|
|
}
|
|
}
|
|
|
|
var buf = new byte[buffer.Length];
|
|
_stream.BeginRead(buf, 0, buffer.Length, new AsyncCallback(OnReadData), buf);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class HIDDeviceDataReceivedEventArgs : EventArgs
|
|
{
|
|
#region Declarations
|
|
|
|
private byte _reportType;
|
|
private byte[] _data;
|
|
|
|
#endregion
|
|
|
|
#region Constructors / Teardown
|
|
|
|
public HIDDeviceDataReceivedEventArgs(byte reportType, byte[] data)
|
|
{
|
|
_reportType = reportType;
|
|
_data = data;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
public byte ReportType
|
|
{
|
|
get
|
|
{
|
|
return _reportType;
|
|
}
|
|
}
|
|
|
|
public byte[] Data
|
|
{
|
|
get
|
|
{
|
|
return _data;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|