init
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user