This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,416 @@
using System;
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.USBFramework
{
public class DeviceManagement : IDisposable
{
public void Dispose()
{
}
public bool DeviceNameMatch(Message m, string mydevicePathName)
{
// Purpose : Compares two device path names. Used to find out if the device name
// : of a recently attached or removed device matches the name of a
// : device the application is communicating with.
// Accepts : m - a WM_DEVICECHANGE message. A call to RegisterDeviceNotification
// : causes WM_DEVICECHANGE messages to be passed to an OnDeviceChange routine.
// : mydevicePathName - a device pathname returned by SetupDiGetDeviceInterfaceDetail
// : in an SP_DEVICE_INTERFACE_DETAIL_DATA structure.
// Returns : True if the names match, False if not.
var devBroadcastDeviceInterface = new DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE_1();
var devBroadcastHeader = new DeviceManagementDeclarations.DEV_BROADCAST_HDR();
// The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
if (devBroadcastHeader.dbch_devicetype != DeviceManagementDeclarations.DBT_DEVTYP_DEVICEINTERFACE) return false;
// The dbch_devicetype parameter indicates that the event applies to a device interface.
// So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure,
// which begins with a DEV_BROADCAST_HDR.
// Obtain the number of characters in dbch_name by subtracting the 28 bytes
// in the other members of the structure and dividing by 2 because there are
// 2 bytes per character.
var stringSize = Convert.ToInt32((devBroadcastHeader.dbch_size - 28) / 2);
// The dbcc_name parameter of DevBroadcastDeviceInterface contains the device name.
// Trim dbcc_name to match the size of the string.
devBroadcastDeviceInterface.dbcc_name = new char[stringSize + 1];
// Marshal data from the unmanaged block pointed to by m.LParam
// to the managed object DevBroadcastDeviceInterface.
Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
// Store the device name in a String.
var deviceNameString = new string(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
//Debug.WriteLine("Device Name = " + DeviceNameString);
//Debug.WriteLine("");
// Compare the name of the newly attached device with the name of the device
// the application is accessing (mydevicePathName).
// Set ignorecase True.
if (string.Compare(deviceNameString, mydevicePathName, true) == 0)
{
// The name matches.
return true;
}
// It's a different device.
return false;
}
public bool FindDeviceFromGuid(System.Guid myGuid, ref string[] devicePathName)
{
// Purpose : Uses SetupDi API functions to retrieve the device path name of an
// : attached device that belongs to an interface class.
// Accepts : myGuid - an interface class GUID.
// : devicePathName - a pointer to an array of strings that will contain
// : the device path names of attached devices.
// Returns : True if at least one device is found, False if not.
var lastDevice = false;
var bufferSize = 0;
var myDeviceInterfaceDetailData = new DeviceManagementDeclarations.SP_DEVICE_INTERFACE_DETAIL_DATA();
var myDeviceInterfaceData = new DeviceManagementDeclarations.SP_DEVICE_INTERFACE_DATA();
int result;
var detailDataBuffer = IntPtr.Zero;
// ***
// API function: SetupDiGetClassDevs
// Purpose:
// Retrieves a device information set for a specified group of devices.
// SetupDiEnumDeviceInterfaces uses the device information set.
// Accepts:
// An interface class GUID
// Null to retrieve information for all device instances
// An optional handle to a top-level window (unused here)
// Flags to limit the returned information to currently present devices
// and devices that expose interfaces in the class specified by the GUID.
// Returns:
// A handle to a device information set for the devices.
// ***
var deviceInfoSet = DeviceManagementDeclarations.SetupDiGetClassDevs(ref myGuid,
null,
0,
DeviceManagementDeclarations.DIGCF_PRESENT | DeviceManagementDeclarations.DIGCF_DEVICEINTERFACE);
var deviceFound = false;
var memberIndex = 0;
try
{
do
{
// Begin with 0 and increment through the device information set until
// no more devices are available.
// The cbSize element of the MyDeviceInterfaceData structure must be set to
// the structure's size in bytes.
// The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);
// ***
// API function:
// SetupDiEnumDeviceInterfaces()
// Purpose: Retrieves a handle to a SP_DEVICE_INTERFACE_DATA
// structure for a device.
// On return, MyDeviceInterfaceData contains the handle to a
// SP_DEVICE_INTERFACE_DATA structure for a detected device.
// Accepts:
// A DeviceInfoSet returned by SetupDiGetClassDevs.
// An interface class GUID.
// An index to specify a device in a device information set.
// A pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
// Returns:
// Non-zero on success, zero on True.
// ***
result = DeviceManagementDeclarations.SetupDiEnumDeviceInterfaces(deviceInfoSet,
IntPtr.Zero,
ref myGuid,
memberIndex,
ref myDeviceInterfaceData);
// Find out if a device information set was retrieved.
if (result == 0)
{
lastDevice = true;
}
else
{
// A device is present.
// ***
// API function:
// SetupDiGetDeviceInterfaceDetail()
// Purpose:
// Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
// containing information about a device.
// To retrieve the information, call this function twice.
// The first time returns the size of the structure.
// The second time returns a pointer to the data.
// Accepts:
// A DeviceInfoSet returned by SetupDiGetClassDevs
// An SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
// A pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA structure to receive information
// about the specified interface.
// The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
// A pointer to a variable that will receive the returned required size of the
// SP_DEVICE_INTERFACE_DETAIL_DATA structure.
// A pointer to an SP_DEVINFO_DATA structure to receive information about the device.
// Returns:
// Non-zero on success, zero on failure.
// ***
DeviceManagementDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
ref myDeviceInterfaceData,
IntPtr.Zero,
0,
ref bufferSize,
IntPtr.Zero);
// Store the structure's size.
myDeviceInterfaceDetailData.cbSize = Marshal.SizeOf(myDeviceInterfaceDetailData);
// Allocate memory for the MyDeviceInterfaceDetailData Structure using the returned buffer size.
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
// Store cbSize in the first 4 bytes of the array
if (IS64_BIT_PROCESS)
{
Marshal.WriteInt64(detailDataBuffer,
(IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
}
else
{
Marshal.WriteInt32(detailDataBuffer,
(IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
}
// Call SetupDiGetDeviceInterfaceDetail again.
// This time, pass a pointer to DetailDataBuffer
// and the returned required buffer size.
DeviceManagementDeclarations.SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
ref myDeviceInterfaceData,
detailDataBuffer,
bufferSize,
ref bufferSize,
IntPtr.Zero);
// Skip over cbsize (4 bytes) to get the address of the devicePathName.
var pdevicePathName = IS64_BIT_PROCESS ? new IntPtr(detailDataBuffer.ToInt64() + 4) : new IntPtr(detailDataBuffer.ToInt32() + 4);
// Get the String containing the devicePathName.
var singledevicePathName = Marshal.PtrToStringAuto(pdevicePathName);
devicePathName[memberIndex] = singledevicePathName;
// Free the memory allocated previously by AllocHGlobal.
Marshal.FreeHGlobal(detailDataBuffer);
detailDataBuffer = IntPtr.Zero;
deviceFound = true;
}
memberIndex++;
} while (!lastDevice);
}
finally
{
if (detailDataBuffer != IntPtr.Zero)
{
// Free the memory allocated previously by AllocHGlobal.
Marshal.FreeHGlobal(detailDataBuffer);
}
if (deviceInfoSet != IntPtr.Zero)
{
// ***
// API function
// summary
// Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
// parameters
// DeviceInfoSet returned by SetupDiGetClassDevs.
// returns
// True on success.
// ***
// Trim the array to the number of devices found.
// ***
// API function:
// SetupDiDestroyDeviceInfoList
// Purpose:
// Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
// Accepts:
// A DeviceInfoSet returned by SetupDiGetClassDevs.
// Returns:
// True on success, False on failure.
// ***
DeviceManagementDeclarations.SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
}
return deviceFound;
}
public bool RegisterForDeviceNotifications(IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
{
// Purpose : Request to receive a notification when a device is attached or removed.
// Accepts : devicePathName - a handle to a device.
// : formHandle - a handle to the window that will receive device events.
// : classGuid - an interface class GUID.
//
// Returns : True on success, False on failure.
// A DEV_BROADCAST_DEVICEINTERFACE header holds information about the request.
var dbdi = new DeviceManagementDeclarations.DEV_BROADCAST_DEVICEINTERFACE();
// Set the parameters in the DEV_BROADCAST_DEVICEINTERFACE structure.
// Set the size.
var size = Marshal.SizeOf(dbdi);
dbdi.dbcc_size = size;
// Request to receive notifications about a class of devices.
dbdi.dbcc_devicetype = DeviceManagementDeclarations.DBT_DEVTYP_DEVICEINTERFACE;
dbdi.dbcc_reserved = 0;
// Specify the interface class to receive notifications about.
dbdi.dbcc_classguid = classGuid;
dbdi.dbcc_name = "";
// Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure.
var buffer = Marshal.AllocHGlobal(size);
// Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
// Set fDeleteOld True to prevent memory leaks.
Marshal.StructureToPtr(dbdi, buffer, true);
// ***
// API function:
// RegisterDeviceNotification
// Purpose:
// Request to receive notification messages when a device in an interface class
// is attached or removed.
// Accepts:
// Aa handle to the window that will receive device events
// A pointer to a DEV_BROADCAST_DEVICEINTERFACE to specify the type of
// device to send notifications for,
// DEVICE_NOTIFY_WINDOW_HANDLE to indicate that Handle is a window handle.
// Returns:
// A device notification handle or NULL on failure.
// ***
deviceNotificationHandle = DeviceManagementDeclarations.RegisterDeviceNotification(formHandle,
buffer,
DeviceManagementDeclarations.DEVICE_NOTIFY_WINDOW_HANDLE);
// Marshal data from the unmanaged block DevBroadcastDeviceInterfaceBuffer to
// the managed object DevBroadcastDeviceInterface
//Marshal.PtrToStructure(buffer, dbdi);
// Free the memory allocated previously by AllocHGlobal.
Marshal.FreeHGlobal(buffer);
// Find out if RegisterDeviceNotification was successful.
if (IS64_BIT_PROCESS)
{
return deviceNotificationHandle.ToInt64() != IntPtr.Zero.ToInt64();
}
return deviceNotificationHandle.ToInt32() != IntPtr.Zero.ToInt32();
}
static readonly bool IS64_BIT_PROCESS = (IntPtr.Size == 8);
public void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)
{
// Purpose : Requests to stop receiving notification messages when a device in an
// interface class is attached or removed.
// Accepts : deviceNotificationHandle - a handle returned previously by
// RegisterDeviceNotification
// ***
// API function: UnregisterDeviceNotification
// Purpose: Stop receiving notification messages.
// Accepts: a handle returned previously by RegisterDeviceNotification
// Returns: True on success, False on failure.
// ***
// Ignore failures.
DeviceManagementDeclarations.UnregisterDeviceNotification(deviceNotificationHandle);
}
public bool GetDeviceRegistryProperty(Guid myGuid)
{
const int maxDevLen = 1000;
// Create a HDEVINFO with all present devices.
var deviceInfoSet = DeviceManagementDeclarations.SetupDiGetClassDevs(ref myGuid, // null?
null, // Enumerator
0,
DeviceManagementDeclarations.DIGCF_PRESENT | DeviceManagementDeclarations.DIGCF_ALLCLASSES);
if ((int)deviceInfoSet == FileIODeclarations.INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return false;
}
// Enumerate through all devices in Set.
DeviceManagementDeclarations.SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = Marshal.SizeOf(typeof(DeviceManagementDeclarations.SP_DEVINFO_DATA));
for (uint i = 0; DeviceManagementDeclarations.SetupDiEnumDeviceInfo(deviceInfoSet, i, out deviceInfoData); i++)
{
var deviceName = new StringBuilder(maxDevLen);
if (!DeviceManagementDeclarations.SetupDiGetDeviceRegistryPropertyA(deviceInfoSet,
deviceInfoData,
DeviceManagementDeclarations.SPDRP_DRIVER,
0,
deviceName,
maxDevLen,
IntPtr.Zero))
{
//incorrect device name:
DeviceManagementDeclarations.SetupDiDestroyDeviceInfoList(deviceInfoSet);
deviceName = new StringBuilder("");
return false;
}
APILogger.Log(deviceName.ToString());
}
if (DeviceManagementDeclarations.GetLastError() != DeviceManagementDeclarations.NO_ERROR &&
DeviceManagementDeclarations.GetLastError() != DeviceManagementDeclarations.ERROR_NO_MORE_ITEMS)
{
try
{
var theGuid = Guid.Empty;
if (null != myGuid) { theGuid = myGuid; }
var w32 = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
APILogger.Log("GetDeviceRegistryProperty(", theGuid.ToString(), ") error - ", w32.Message);
}
catch { }
// Insert error handling here.
return false;
}
// Cleanup
DeviceManagementDeclarations.SetupDiDestroyDeviceInfoList(deviceInfoSet);
return true;
}
}
}