You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

557 lines
24 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
namespace JwKdsV.Core.HWiNFO
{
[StructLayout(LayoutKind.Sequential)]
public struct T_VIDPID
{
public ushort VendorID; // 供应商标识
public ushort ProductID; // 产品编号
}
/// <summary>
/// 基于WDK获取系统设备的VIDPID
/// </summary>
public static partial class HWiNFO
{
/// <summary>
/// 结合设备安装类GUID和设备接口类GUID获取设备VIDPID
/// </summary>
/// <param name="SetupClassGuid">设备安装类GUIDEmpty忽视</param>
/// <param name="InterfaceClassGuid">设备接口类GUIDEmpty忽视</param>
/// <returns>设备VIDPID列表</returns>
/// <remarks>
/// 优点直接通过设备实例ID提取VIDPID从而无需获取设备路径来读写IO
/// </remarks>
public static T_VIDPID[] WDK_QueryVidPid(Guid SetupClassGuid, Guid InterfaceClassGuid)
{
// 根据设备安装类GUID创建空的设备信息集合
IntPtr DeviceInfoSet;
if (SetupClassGuid.Equals(Guid.Empty))
{
DeviceInfoSet = SetupApi.SetupDiCreateDeviceInfoList(IntPtr.Zero, IntPtr.Zero);
}
else
{
DeviceInfoSet = SetupApi.SetupDiCreateDeviceInfoList(ref SetupClassGuid, IntPtr.Zero);
}
if (DeviceInfoSet == Kernel32.INVALID_HANDLE_VALUE) return null;
// 根据设备接口类GUID创建新的设备信息集合
IntPtr hDevInfo;
if (InterfaceClassGuid.Equals(Guid.Empty))
{
hDevInfo = SetupApi.SetupDiGetClassDevsEx(
IntPtr.Zero,
null,
IntPtr.Zero,
SetupApi.DIGCF.DIGCF_ALLCLASSES | SetupApi.DIGCF.DIGCF_INTERFACEDEVICE | SetupApi.DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
else
{
hDevInfo = SetupApi.SetupDiGetClassDevsEx(
ref InterfaceClassGuid,
null,
IntPtr.Zero,
SetupApi.DIGCF.DIGCF_INTERFACEDEVICE | SetupApi.DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
if (hDevInfo == Kernel32.INVALID_HANDLE_VALUE)
{
SetupApi.SetupDiDestroyDeviceInfoList(DeviceInfoSet); // 删除设备信息集
return null;
}
// 枚举所有设备
List<T_VIDPID> DeviceList = new List<T_VIDPID>();
// 存储设备实例ID
StringBuilder DeviceInstanceId = new StringBuilder(256);
// 获取设备信息数据
uint DeviceIndex = 0;
SetupApi.SP_DEVINFO_DATA DeviceInfoData = SetupApi.SP_DEVINFO_DATA.Empty;
while (SetupApi.SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex++, ref DeviceInfoData))
{ // 获取设备实例ID
if (SetupApi.SetupDiGetDeviceInstanceId(hDevInfo, ref DeviceInfoData, DeviceInstanceId, DeviceInstanceId.Capacity, IntPtr.Zero))
{
string PNPDeviceID = DeviceInstanceId.ToString();
Match match = Regex.Match(PNPDeviceID, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}");
if (match.Success)
{
T_VIDPID Entity;
Entity.VendorID = Convert.ToUInt16(match.Value.Substring(4, 4), 16); // 供应商标识
Entity.ProductID = Convert.ToUInt16(match.Value.Substring(13, 4), 16); // 产品编号
if (!DeviceList.Contains(Entity)) DeviceList.Add(Entity);
}
}
}
SetupApi.SetupDiDestroyDeviceInfoList(hDevInfo);
if (DeviceList.Count == 0) return null; else return DeviceList.ToArray();
}
/// <summary>
/// 验证设备的VIDPID
/// </summary>
/// <param name="VendorID">设备VID</param>
/// <param name="ProductID">设备PID</param>
/// <param name="SetupClassGuid">设备安装类GUIDEmpty忽视</param>
/// <param name="InterfaceClassGuid">设备接口类GUIDEmpty忽视</param>
/// <returns>
/// true匹配成功
/// false匹配失败
/// </returns>
public static bool WDK_VIDPIDMatch(ushort VendorID, ushort ProductID, Guid SetupClassGuid, Guid InterfaceClassGuid)
{
// 根据设备安装类GUID创建空的设备信息集合
IntPtr DeviceInfoSet;
if (SetupClassGuid.Equals(Guid.Empty))
{
DeviceInfoSet = SetupApi.SetupDiCreateDeviceInfoList(IntPtr.Zero, IntPtr.Zero);
}
else
{
DeviceInfoSet = SetupApi.SetupDiCreateDeviceInfoList(ref SetupClassGuid, IntPtr.Zero);
}
if (DeviceInfoSet == Kernel32.INVALID_HANDLE_VALUE) return false;
// 根据设备接口类GUID创建新的设备信息集合
IntPtr hDevInfo;
if (InterfaceClassGuid.Equals(Guid.Empty))
{
hDevInfo = SetupApi.SetupDiGetClassDevsEx(
IntPtr.Zero,
null,
IntPtr.Zero,
SetupApi.DIGCF.DIGCF_ALLCLASSES | SetupApi.DIGCF.DIGCF_INTERFACEDEVICE | SetupApi.DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
else
{
hDevInfo = SetupApi.SetupDiGetClassDevsEx(
ref InterfaceClassGuid,
null,
IntPtr.Zero,
SetupApi.DIGCF.DIGCF_INTERFACEDEVICE | SetupApi.DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
if (hDevInfo == Kernel32.INVALID_HANDLE_VALUE)
{
SetupApi.SetupDiDestroyDeviceInfoList(DeviceInfoSet); // 删除设备信息集
return false;
}
// 存储设备实例ID
StringBuilder DeviceInstanceId = new StringBuilder(256);
// 获取设备信息数据
uint DeviceIndex = 0;
SetupApi.SP_DEVINFO_DATA DeviceInfoData = SetupApi.SP_DEVINFO_DATA.Empty;
while (SetupApi.SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex++, ref DeviceInfoData))
{ // 获取设备实例ID
if (SetupApi.SetupDiGetDeviceInstanceId(hDevInfo, ref DeviceInfoData, DeviceInstanceId, DeviceInstanceId.Capacity, IntPtr.Zero))
{
string PNPDeviceID = DeviceInstanceId.ToString();
Match match = Regex.Match(PNPDeviceID, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}");
if (match.Success)
{ // 供应商标识
if (VendorID == Convert.ToUInt16(match.Value.Substring(4, 4), 16))
{ // 产品编号
if (ProductID == Convert.ToUInt16(match.Value.Substring(13, 4), 16))
{
SetupApi.SetupDiDestroyDeviceInfoList(hDevInfo);
return true;
}
}
}
}
}
SetupApi.SetupDiDestroyDeviceInfoList(hDevInfo);
return false;
}
/// <summary>
/// 输出VIDPID信息到指定INI文件
/// </summary>
/// <param name="iniFileName">要保存的ini文件名</param>
/// <returns>
/// true成功
/// false失败
/// </returns>
public static bool WDK_VIDPIDPrint(string iniFileName)
{
if (string.IsNullOrEmpty(iniFileName)) return false;
LINQToINI iniFile = new LINQToINI();
// VIDPID
T_VIDPID[] Properties = WDK_QueryVidPid(Guid.Empty, Guid.Empty);
if (Properties != null)
{
for (int i = 0; i < Properties.Length; i++)
{
iniFile.WriteProfileString("VIDPID", i.ToString(), Properties[i].VendorID.ToString("X4") + "-" + Properties[i].ProductID.ToString("X4"));
}
}
iniFile.Save(iniFileName);
return true;
}
/// <summary>
/// 通过WDK获取网卡原生MAC地址
/// </summary>
/// <param name="isIncludeUSB">是否包含USB网卡默认不包含USB网卡</param>
/// <returns>获取到的网卡原生MAC地址集合</returns>
public static string[] WDK_QueryMacAddress(bool isIncludeUSB = false)
{ // 获取设备信息集
Guid DeviceInterfaceClass = new Guid(0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C);
IntPtr hDevInfo = SetupApi.SetupDiGetClassDevs(ref DeviceInterfaceClass, null, IntPtr.Zero, SetupApi.DIGCF.DIGCF_PRESENT | SetupApi.DIGCF.DIGCF_INTERFACEDEVICE);
if (hDevInfo == Kernel32.INVALID_HANDLE_VALUE) return null;
// 枚举设备信息集中所有设备
List<string> DeviceList = new List<string>();
SetupApi.SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
for (uint MemberIndex = 0; ; MemberIndex++)
{ // 获取设备接口
if (!SetupApi.SetupDiEnumDeviceInterfaces(hDevInfo, null, ref DeviceInterfaceClass, MemberIndex, ref DeviceInterfaceData))
{ // 设备枚举完毕
break;
}
// 获取设备细节信息
SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = new SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8)
DeviceInterfaceDetailData.cbSize = 8;
else
DeviceInterfaceDetailData.cbSize = 4 + Marshal.SystemDefaultCharSize;
if (SetupApi.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, ref DeviceInterfaceDetailData, Marshal.SizeOf(DeviceInterfaceDetailData), IntPtr.Zero, IntPtr.Zero))
{ // 剔除虚拟网卡
if (string.Compare(DeviceInterfaceDetailData.DevicePath, 4, "root", 0, 4, StringComparison.OrdinalIgnoreCase) == 0) continue;
if (isIncludeUSB)
{ // 剔除USB网卡
if (string.Compare(DeviceInterfaceDetailData.DevicePath, 4, "usb", 0, 3, StringComparison.OrdinalIgnoreCase) == 0) continue;
}
string PermanentAddress = GetPermanentAddressByDevicePath(DeviceInterfaceDetailData.DevicePath);
if (!string.IsNullOrEmpty(PermanentAddress) && !DeviceList.Contains(PermanentAddress))
DeviceList.Add(PermanentAddress);
}
}
SetupApi.SetupDiDestroyDeviceInfoList(hDevInfo);
if (DeviceList.Count == 0) return null; else return DeviceList.ToArray();
}
/// <summary>
/// 通过设备路径获取网卡原生MAC地址
/// </summary>
/// <param name="DevicePath">设备路径</param>
/// <returns>网卡原生MAC地址</returns>
private static string GetPermanentAddressByDevicePath(string DevicePath)
{
// 获取设备句柄
IntPtr DeviceHandle = Kernel32.CreateFile(DevicePath, NativeFileAccess.SPECIAL, NativeFileShare.FILE_SHARE_READ | NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero);
if (DeviceHandle != Kernel32.INVALID_HANDLE_VALUE)
{
byte[] ucData = new byte[8];
int nBytesReturned;
// 获取原生MAC地址
const int IOCTL_NDIS_QUERY_GLOBAL_STATS = 0x00170002;
uint OID_802_3_PERMANENT_ADDRESS = 0x01010101;
bool isOK = Kernel32.DeviceIoControl(DeviceHandle, IOCTL_NDIS_QUERY_GLOBAL_STATS, ref OID_802_3_PERMANENT_ADDRESS, Marshal.SizeOf(OID_802_3_PERMANENT_ADDRESS), ucData, ucData.Length, out nBytesReturned, IntPtr.Zero);
Kernel32.CloseHandle(DeviceHandle);
if (isOK)
{
StringBuilder sb = new StringBuilder(nBytesReturned << 1);
for (int i = 0; i < nBytesReturned; i++)
{
sb.Append(ucData[i].ToString("X2"));
}
return sb.ToString();
}
}
return null;
}
/// <summary>
/// 获取硬盘序列号
/// </summary>
/// <returns>获取到的硬盘序列号集合</returns>
public static string[] WDK_QueryDiskDrive()
{
// 获取设备信息集
Guid DeviceInterfaceClass = new Guid(0x53F56307, 0xB6BF, 0x11D0, 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B);
IntPtr hDevInfo = SetupApi.SetupDiGetClassDevs(ref DeviceInterfaceClass, null, IntPtr.Zero, SetupApi.DIGCF.DIGCF_PRESENT | SetupApi.DIGCF.DIGCF_INTERFACEDEVICE);
if (hDevInfo == Kernel32.INVALID_HANDLE_VALUE) return null;
// 枚举设备信息集中所有设备
List<string> DeviceList = new List<string>();
SetupApi.SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = SetupApi.SP_DEVICE_INTERFACE_DATA.Empty;
for (uint MemberIndex = 0; ; MemberIndex++)
{ // 获取设备接口
if (!SetupApi.SetupDiEnumDeviceInterfaces(hDevInfo, null, ref DeviceInterfaceClass, MemberIndex, ref DeviceInterfaceData))
{ // 设备枚举完毕
break;
}
// 获取设备细节信息
SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = new SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8)
DeviceInterfaceDetailData.cbSize = 8;
else
DeviceInterfaceDetailData.cbSize = 4 + Marshal.SystemDefaultCharSize;
if (SetupApi.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, ref DeviceInterfaceDetailData, Marshal.SizeOf(DeviceInterfaceDetailData), IntPtr.Zero, IntPtr.Zero))
{
string SerialNumber = GetHarddiskSerialNumberWithZeroRights(DeviceInterfaceDetailData.DevicePath);
if (!string.IsNullOrEmpty(SerialNumber) && !DeviceList.Contains(SerialNumber))
DeviceList.Add(SerialNumber);
}
}
SetupApi.SetupDiDestroyDeviceInfoList(hDevInfo);
if (DeviceList.Count == 0) return null; else return DeviceList.ToArray();
}
/// <summary>
/// 通过设备路径获取硬盘序列号
/// </summary>
/// <param name="DevicePath">设备路径</param>
/// <returns>硬盘序列号</returns>
private static string GetHarddiskSerialNumberWithZeroRights(string DevicePath)
{
const uint IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400; // 控制代码
string SerialNumber = null;
// 获取硬盘句柄
IntPtr hDeviceFile = Kernel32.CreateFile(DevicePath, NativeFileAccess.FILE_SPECIAL, NativeFileShare.FILE_SHARE_READ | NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero);
if (hDeviceFile != Kernel32.INVALID_HANDLE_VALUE)
{
STORAGE_PROPERTY_QUERY PropertyQuery;
PropertyQuery.PropertyId = STORAGE_PROPERTY_ID.StorageDeviceProperty;
PropertyQuery.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery;
PropertyQuery.AdditionalParameters = 0;
STORAGE_DESCRIPTOR_HEADER DescriptorHeader = new STORAGE_DESCRIPTOR_HEADER();
int dwBytesReturned;
if (Kernel32.DeviceIoControl(hDeviceFile, IOCTL_STORAGE_QUERY_PROPERTY, ref PropertyQuery, Marshal.SizeOf(PropertyQuery), ref DescriptorHeader, Marshal.SizeOf(DescriptorHeader), out dwBytesReturned, IntPtr.Zero))
{
IntPtr DescriptorBuffer = Marshal.AllocHGlobal(DescriptorHeader.Size);
if (Kernel32.DeviceIoControl(hDeviceFile, IOCTL_STORAGE_QUERY_PROPERTY, ref PropertyQuery, Marshal.SizeOf(PropertyQuery), DescriptorBuffer, DescriptorHeader.Size, out dwBytesReturned, IntPtr.Zero))
{
STORAGE_DEVICE_DESCRIPTOR DeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR)Marshal.PtrToStructure(DescriptorBuffer, typeof(STORAGE_DEVICE_DESCRIPTOR));
if (DeviceDescriptor.SerialNumberOffset != 0)
{
SerialNumber = ProcessHardDiskSerialNumber(Marshal.PtrToStringAnsi(IntPtr.Add(DescriptorBuffer, DeviceDescriptor.SerialNumberOffset)));
}
}
Marshal.FreeHGlobal(DescriptorBuffer);
}
Kernel32.CloseHandle(hDeviceFile);
}
return SerialNumber;
}
/// <summary>
/// 查看系统中是否存在指定标识的硬件设备
/// </summary>
/// <param name="CPUID">处理器标识,可以为空</param>
/// <param name="HardDiskSerialNumber">硬盘序列号,可以为空</param>
/// <param name="MacAddress">网卡MAC地址已剔除虚拟网卡和USB网卡可以为空</param>
/// <returns>
/// true匹配成功
/// false匹配失败
/// </returns>
/// <remarks>
/// 说明:
/// 对设备标识不区分大小写
/// 空项不做判断,非空项必须全部满足
/// </remarks>
public static bool WDK_DeviceMatch(string CPUID, string HardDiskSerialNumber, string MacAddress)
{
// CPU ID
if (!string.IsNullOrEmpty(CPUID))
{ // 基于WMI查询
string[] Properties = WMI_DeviceQuery(4);
if (Properties == null) return false;
bool IsExist = false;
foreach (string Item in Properties)
{
if (CPUID.Equals(Item, StringComparison.OrdinalIgnoreCase))
{
IsExist = true;
break;
}
}
if (!IsExist) return false;
}
// 硬盘序列号
if (!string.IsNullOrEmpty(HardDiskSerialNumber))
{ // 基于WMI查询
string[] Properties = WDK_QueryDiskDrive();
if (Properties == null) return false;
bool IsExist = false;
foreach (string Item in Properties)
{
if (HardDiskSerialNumber.Equals(Item, StringComparison.OrdinalIgnoreCase))
{
IsExist = true;
break;
}
}
if (!IsExist) return false;
}
// 网卡原生MAC地址
if (!string.IsNullOrEmpty(MacAddress))
{ // 基于WDK查询
string[] Properties = WDK_QueryMacAddress();
if (Properties == null) return false;
bool IsExist = false;
foreach (string Item in Properties)
{
if (MacAddress.Equals(Item, StringComparison.OrdinalIgnoreCase))
{
IsExist = true;
break;
}
}
if (!IsExist) return false;
}
// 判断程序是否是在VMware虚拟机中运行
if (WDK_IsVMware()) return false; else return true;
}
/// <summary>
/// 输出硬件信息到指定INI文件
/// </summary>
/// <param name="iniFileName">要保存的ini文件名</param>
/// <returns>
/// true成功
/// false失败
/// </returns>
public static bool WDK_DeviceInfoPrint(string iniFileName)
{
if (string.IsNullOrEmpty(iniFileName)) return false;
LINQToINI iniFile = new LINQToINI();
// 网卡原生MAC地址
string[] Properties = WDK_QueryMacAddress();
if (Properties != null)
{
for (int i = 0; i < Properties.Length; i++)
{
iniFile.WriteProfileString("MacAddress", i.ToString(), Properties[i]);
}
}
// 硬盘序列号
Properties = WDK_QueryDiskDrive();
if (Properties != null)
{
for (int i = 0; i < Properties.Length; i++)
{
iniFile.WriteProfileString("HardDiskSerialNumber", i.ToString(), Properties[i]);
}
}
// CPU ID
Properties = WMI_DeviceQuery(4);
if (Properties != null)
{
for (int i = 0; i < Properties.Length; i++)
{
iniFile.WriteProfileString("CPUID", i.ToString(), Properties[i]);
}
}
iniFile.Save(iniFileName);
return true;
}
/// <summary>
/// 判断程序是否在VMware虚拟机中运行
/// </summary>
/// <returns>
/// true程序是在VMware虚拟机中运行
/// false程序不是在VMware虚拟机中运行
/// </returns>
public static bool WDK_IsVMware()
{
const uint IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400; // 控制代码
bool IsOK = false;
// 获取硬盘句柄
IntPtr hDeviceFile = Kernel32.CreateFile(@"\\.\PhysicalDrive0", NativeFileAccess.FILE_SPECIAL, NativeFileShare.FILE_SHARE_READ | NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero);
if (hDeviceFile != Kernel32.INVALID_HANDLE_VALUE)
{
STORAGE_PROPERTY_QUERY PropertyQuery;
PropertyQuery.PropertyId = STORAGE_PROPERTY_ID.StorageDeviceProperty;
PropertyQuery.QueryType = STORAGE_QUERY_TYPE.PropertyStandardQuery;
PropertyQuery.AdditionalParameters = 0;
STORAGE_DESCRIPTOR_HEADER DescriptorHeader = new STORAGE_DESCRIPTOR_HEADER();
int dwBytesReturned;
if (Kernel32.DeviceIoControl(hDeviceFile, IOCTL_STORAGE_QUERY_PROPERTY, ref PropertyQuery, Marshal.SizeOf(PropertyQuery), ref DescriptorHeader, Marshal.SizeOf(DescriptorHeader), out dwBytesReturned, IntPtr.Zero))
{
IntPtr DescriptorBuffer = Marshal.AllocHGlobal(DescriptorHeader.Size);
if (Kernel32.DeviceIoControl(hDeviceFile, IOCTL_STORAGE_QUERY_PROPERTY, ref PropertyQuery, Marshal.SizeOf(PropertyQuery), DescriptorBuffer, DescriptorHeader.Size, out dwBytesReturned, IntPtr.Zero))
{
STORAGE_DEVICE_DESCRIPTOR DeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR)Marshal.PtrToStructure(DescriptorBuffer, typeof(STORAGE_DEVICE_DESCRIPTOR));
if (DeviceDescriptor.VendorIdOffset != 0)
{
string vendorId = Marshal.PtrToStringAnsi(IntPtr.Add(DescriptorBuffer, DeviceDescriptor.VendorIdOffset));
if (!string.IsNullOrEmpty(vendorId) && vendorId.IndexOf("VMware") >= 0)
{
IsOK = true;
}
}
}
Marshal.FreeHGlobal(DescriptorBuffer);
}
Kernel32.CloseHandle(hDeviceFile);
}
return IsOK;
}
}
}