mirror of
https://github.com/ckaczor/WorkIndicator.git
synced 2026-01-14 01:25:45 -05:00
Initial commit
This commit is contained in:
357
Delcom/DeviceManagement.cs
Normal file
357
Delcom/DeviceManagement.cs
Normal file
@@ -0,0 +1,357 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace WorkIndicator.Delcom
|
||||
{
|
||||
sealed internal partial class DeviceManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="m"> a WM_DEVICECHANGE message. A call to RegisterDeviceNotification
|
||||
/// causes WM_DEVICECHANGE messages to be passed to an OnDeviceChange routine.. </param>
|
||||
/// <param name="mydevicePathName"> a device pathname returned by
|
||||
/// SetupDiGetDeviceInterfaceDetail in an SP_DEVICE_INTERFACE_DETAIL_DATA structure. </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// True if the names match, False if not.
|
||||
/// </returns>
|
||||
///
|
||||
internal Boolean DeviceNameMatch(Message m, String mydevicePathName)
|
||||
{
|
||||
DevBroadcastDeviceInterface1 devBroadcastDeviceInterface = new DevBroadcastDeviceInterface1();
|
||||
DevBroadcastHdr devBroadcastHeader = new DevBroadcastHdr();
|
||||
|
||||
// The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
|
||||
|
||||
Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
|
||||
|
||||
if ((devBroadcastHeader.dbch_devicetype == DbtDevTypDeviceInterface))
|
||||
{
|
||||
// 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 32 bytes
|
||||
// in the strucutre that are not part of dbch_name and dividing by 2 because there are
|
||||
// 2 bytes per character.
|
||||
|
||||
Int32 stringSize = Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 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.
|
||||
String deviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
|
||||
|
||||
// Compare the name of the newly attached device with the name of the device
|
||||
// the application is accessing (mydevicePathName).
|
||||
// Set ignorecase True.
|
||||
|
||||
return String.Compare(deviceNameString, mydevicePathName, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use SetupDi API functions to retrieve the device path name of an
|
||||
/// attached device that belongs to a device interface class.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="myGuid"> an interface class GUID. </param>
|
||||
/// <param name="devicePathName"> a pointer to the device path name
|
||||
/// of an attached device. </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// True if a device is found, False if not.
|
||||
/// </returns>
|
||||
internal Boolean FindDeviceFromGuid(Guid myGuid, ref String[] devicePathName)
|
||||
{
|
||||
Int32 bufferSize = 0;
|
||||
IntPtr detailDataBuffer = IntPtr.Zero;
|
||||
IntPtr deviceInfoSet = new IntPtr();
|
||||
Boolean lastDevice = false;
|
||||
SpDeviceInterfaceData deviceInterfaceData = new SpDeviceInterfaceData();
|
||||
|
||||
try
|
||||
{
|
||||
// ***
|
||||
// API function
|
||||
|
||||
// summary
|
||||
// Retrieves a device information set for a specified group of devices.
|
||||
// SetupDiEnumDeviceInterfaces uses the device information set.
|
||||
|
||||
// parameters
|
||||
// Interface class GUID.
|
||||
// Null to retrieve information for all device instances.
|
||||
// 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
|
||||
// Handle to a device information set for the devices.
|
||||
// ***
|
||||
|
||||
deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DigCfPresent | DigCfDeviceInterface);
|
||||
|
||||
Boolean deviceFound = false;
|
||||
Int32 memberIndex = 0;
|
||||
|
||||
// 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.
|
||||
|
||||
deviceInterfaceData.CbSize = Marshal.SizeOf(deviceInterfaceData);
|
||||
|
||||
do
|
||||
{
|
||||
// Begin with 0 and increment through the device information set until
|
||||
// no more devices are available.
|
||||
|
||||
// ***
|
||||
// API function
|
||||
|
||||
// summary
|
||||
// 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.
|
||||
|
||||
// parameters
|
||||
// DeviceInfoSet returned by SetupDiGetClassDevs.
|
||||
// Optional SP_DEVINFO_DATA structure that defines a device instance
|
||||
// that is a member of a device information set.
|
||||
// Device interface GUID.
|
||||
// Index to specify a device in a device information set.
|
||||
// Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
|
||||
|
||||
// Returns
|
||||
// True on success.
|
||||
// ***
|
||||
|
||||
Boolean success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref deviceInterfaceData);
|
||||
|
||||
// Find out if a device information set was retrieved.
|
||||
|
||||
if (!success)
|
||||
{
|
||||
lastDevice = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A device is present.
|
||||
|
||||
// ***
|
||||
// API function:
|
||||
|
||||
// summary:
|
||||
// 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.
|
||||
|
||||
// parameters
|
||||
// DeviceInfoSet returned by SetupDiGetClassDevs
|
||||
// SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
|
||||
// A returned 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.
|
||||
// Pointer to a variable that will receive the returned required size of the
|
||||
// SP_DEVICE_INTERFACE_DETAIL_DATA structure.
|
||||
// Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.
|
||||
|
||||
// Returns
|
||||
// True on success.
|
||||
// ***
|
||||
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
|
||||
|
||||
// Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
|
||||
|
||||
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
|
||||
|
||||
// Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
|
||||
|
||||
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.
|
||||
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero);
|
||||
|
||||
// Skip over cbsize (4 bytes) to get the address of the devicePathName.
|
||||
|
||||
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);
|
||||
|
||||
// Get the String containing the devicePathName.
|
||||
|
||||
devicePathName[memberIndex] = Marshal.PtrToStringAuto(pDevicePathName);
|
||||
|
||||
deviceFound = true;
|
||||
}
|
||||
memberIndex = memberIndex + 1;
|
||||
}
|
||||
while (lastDevice != true);
|
||||
|
||||
return deviceFound;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (detailDataBuffer != IntPtr.Zero)
|
||||
{
|
||||
// Free the memory allocated previously by AllocHGlobal.
|
||||
|
||||
Marshal.FreeHGlobal(detailDataBuffer);
|
||||
}
|
||||
// ***
|
||||
// API function
|
||||
|
||||
// summary
|
||||
// Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
|
||||
|
||||
// parameters
|
||||
// DeviceInfoSet returned by SetupDiGetClassDevs.
|
||||
|
||||
// returns
|
||||
// True on success.
|
||||
// ***
|
||||
|
||||
if (deviceInfoSet != IntPtr.Zero)
|
||||
{
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests to receive a notification when a device is attached or removed.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="devicePathName"> handle to a device. </param>
|
||||
/// <param name="formHandle"> handle to the window that will receive device events. </param>
|
||||
/// <param name="classGuid"> device interface GUID. </param>
|
||||
/// <param name="deviceNotificationHandle"> returned device notification handle. </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// True on success.
|
||||
/// </returns>
|
||||
///
|
||||
internal Boolean RegisterForDeviceNotifications(String devicePathName, IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
|
||||
{
|
||||
// A DEV_BROADCAST_DEVICEINTERFACE header holds information about the request.
|
||||
|
||||
DevBroadcastDeviceInterface devBroadcastDeviceInterface = new DevBroadcastDeviceInterface();
|
||||
IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
// Set the parameters in the DEV_BROADCAST_DEVICEINTERFACE structure.
|
||||
|
||||
// Set the size.
|
||||
|
||||
Int32 size = Marshal.SizeOf(devBroadcastDeviceInterface);
|
||||
devBroadcastDeviceInterface.dbcc_size = size;
|
||||
|
||||
// Request to receive notifications about a class of devices.
|
||||
|
||||
devBroadcastDeviceInterface.dbcc_devicetype = DbtDevTypDeviceInterface;
|
||||
|
||||
devBroadcastDeviceInterface.dbcc_reserved = 0;
|
||||
|
||||
// Specify the interface class to receive notifications about.
|
||||
|
||||
devBroadcastDeviceInterface.dbcc_classguid = classGuid;
|
||||
|
||||
// Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure.
|
||||
|
||||
devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
|
||||
|
||||
// Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
|
||||
// Set fDeleteOld True to prevent memory leaks.
|
||||
|
||||
Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
|
||||
|
||||
// ***
|
||||
// API function
|
||||
|
||||
// summary
|
||||
// Request to receive notification messages when a device in an interface class
|
||||
// is attached or removed.
|
||||
|
||||
// parameters
|
||||
// Handle to the window that will receive device events.
|
||||
// Pointer to a DEV_BROADCAST_DEVICEINTERFACE to specify the type of
|
||||
// device to send notifications for.
|
||||
// DEVICE_NOTIFY_WINDOW_HANDLE indicates the handle is a window handle.
|
||||
|
||||
// Returns
|
||||
// Device notification handle or NULL on failure.
|
||||
// ***
|
||||
|
||||
deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DeviceNotifyWindowHandle);
|
||||
|
||||
// Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to
|
||||
// the managed object devBroadcastDeviceInterface
|
||||
|
||||
Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
|
||||
|
||||
return deviceNotificationHandle.ToInt32() != IntPtr.Zero.ToInt32();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
|
||||
{
|
||||
// Free the memory allocated previously by AllocHGlobal.
|
||||
|
||||
Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Requests to stop receiving notification messages when a device in an
|
||||
/// interface class is attached or removed.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="deviceNotificationHandle"> handle returned previously by
|
||||
/// RegisterDeviceNotification. </param>
|
||||
internal void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)
|
||||
{
|
||||
// ***
|
||||
// API function
|
||||
|
||||
// summary
|
||||
// Stop receiving notification messages.
|
||||
|
||||
// parameters
|
||||
// Handle returned previously by RegisterDeviceNotification.
|
||||
|
||||
// returns
|
||||
// True on success.
|
||||
// ***
|
||||
|
||||
// Ignore failures.
|
||||
|
||||
UnregisterDeviceNotification(deviceNotificationHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user