sl@0: using System;
sl@0: using System.Diagnostics;
sl@0: using System.Runtime.InteropServices;
sl@0: using System.Windows.Forms;
sl@0:
sl@0: namespace GenericHid
sl@0: {
sl@0: ///
sl@0: /// Routine for detecting devices using Win32 SetupDi functions.
sl@0: ///
sl@0: ///
sl@0: sealed internal partial class DeviceManagement
sl@0: {
sl@0: private const String ModuleName = "Device Management";
sl@0:
sl@0: ///
sl@0: /// Provides a central mechanism for exception handling.
sl@0: /// Displays a message box that describes the exception.
sl@0: ///
sl@0: ///
sl@0: /// the module where the exception occurred.
sl@0: /// the exception
sl@0:
sl@0: internal static void DisplayException(String name, Exception e)
sl@0: {
sl@0: try
sl@0: {
sl@0: // Create an error message.
sl@0:
sl@0: String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + name + Environment.NewLine + "Method: " +
sl@0: e.TargetSite.Name;
sl@0:
sl@0: const String caption = "Unexpected Exception";
sl@0:
sl@0: MessageBox.Show(message, caption, MessageBoxButtons.OK);
sl@0: Debug.Write(message);
sl@0: }
sl@0: catch (Exception ex)
sl@0: {
sl@0: DisplayException(ModuleName, ex);
sl@0: throw;
sl@0: }
sl@0: }
sl@0:
sl@0: ///
sl@0: /// Use SetupDi API functions to retrieve the device path name of an
sl@0: /// attached device that belongs to a device interface class.
sl@0: ///
sl@0: ///
sl@0: /// an interface class GUID.
sl@0: /// a pointer to the device path name
sl@0: /// of an attached device.
sl@0: ///
sl@0: ///
sl@0: /// True if a device is found, False if not.
sl@0: ///
sl@0:
sl@0: internal Boolean FindDeviceFromGuid(Guid myGuid, ref String[] devicePathName)
sl@0: {
sl@0: Int32 bufferSize = 0;
sl@0: var deviceInfoSet = new IntPtr();
sl@0: Boolean lastDevice = false;
sl@0: var myDeviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
sl@0:
sl@0: try
sl@0: {
sl@0: Int32 memberIndex;
sl@0:
sl@0: // ***
sl@0: // API function
sl@0:
sl@0: // summary
sl@0: // Retrieves a device information set for a specified group of devices.
sl@0: // SetupDiEnumDeviceInterfaces uses the device information set.
sl@0:
sl@0: // parameters
sl@0: // Interface class GUID.
sl@0: // Null to retrieve information for all device instances.
sl@0: // Optional handle to a top-level window (unused here).
sl@0: // Flags to limit the returned information to currently present devices
sl@0: // and devices that expose interfaces in the class specified by the GUID.
sl@0:
sl@0: // Returns
sl@0: // Handle to a device information set for the devices.
sl@0: // ***
sl@0:
sl@0: deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);
sl@0:
sl@0: bool deviceFound = false;
sl@0: memberIndex = 0;
sl@0:
sl@0: // The cbSize element of the MyDeviceInterfaceData structure must be set to
sl@0: // the structure's size in bytes.
sl@0: // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
sl@0:
sl@0: myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);
sl@0:
sl@0: do
sl@0: {
sl@0: // Begin with 0 and increment through the device information set until
sl@0: // no more devices are available.
sl@0:
sl@0: // ***
sl@0: // API function
sl@0:
sl@0: // summary
sl@0: // Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
sl@0: // On return, MyDeviceInterfaceData contains the handle to a
sl@0: // SP_DEVICE_INTERFACE_DATA structure for a detected device.
sl@0:
sl@0: // parameters
sl@0: // DeviceInfoSet returned by SetupDiGetClassDevs.
sl@0: // Optional SP_DEVINFO_DATA structure that defines a device instance
sl@0: // that is a member of a device information set.
sl@0: // Device interface GUID.
sl@0: // Index to specify a device in a device information set.
sl@0: // Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
sl@0:
sl@0: // Returns
sl@0: // True on success.
sl@0: // ***
sl@0:
sl@0: Boolean success = NativeMethods.SetupDiEnumDeviceInterfaces
sl@0: (deviceInfoSet,
sl@0: IntPtr.Zero,
sl@0: ref myGuid,
sl@0: memberIndex,
sl@0: ref myDeviceInterfaceData);
sl@0:
sl@0: // Find out if a device information set was retrieved.
sl@0:
sl@0: if (!success)
sl@0: {
sl@0: lastDevice = true;
sl@0: }
sl@0: else
sl@0: {
sl@0: // A device is present.
sl@0:
sl@0: // ***
sl@0: // API function:
sl@0:
sl@0: // summary:
sl@0: // Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
sl@0: // containing information about a device.
sl@0: // To retrieve the information, call this function twice.
sl@0: // The first time returns the size of the structure.
sl@0: // The second time returns a pointer to the data.
sl@0:
sl@0: // parameters
sl@0: // DeviceInfoSet returned by SetupDiGetClassDevs
sl@0: // SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
sl@0: // A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA
sl@0: // Structure to receive information about the specified interface.
sl@0: // The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
sl@0: // Pointer to a variable that will receive the returned required size of the
sl@0: // SP_DEVICE_INTERFACE_DETAIL_DATA structure.
sl@0: // Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.
sl@0:
sl@0: // Returns
sl@0: // True on success.
sl@0: // ***
sl@0:
sl@0: NativeMethods.SetupDiGetDeviceInterfaceDetail
sl@0: (deviceInfoSet,
sl@0: ref myDeviceInterfaceData,
sl@0: IntPtr.Zero,
sl@0: 0,
sl@0: ref bufferSize,
sl@0: IntPtr.Zero);
sl@0:
sl@0: // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
sl@0:
sl@0: IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
sl@0:
sl@0: // Store cbSize in the first bytes of the array. Adjust for 32- and 64-bit systems.
sl@0:
sl@0: Int32 cbsize;
sl@0:
sl@0: if (IntPtr.Size == 4)
sl@0: {
sl@0: cbsize = 4 + Marshal.SystemDefaultCharSize;
sl@0: }
sl@0: else
sl@0: {
sl@0: cbsize = 8;
sl@0: }
sl@0:
sl@0: Marshal.WriteInt32(detailDataBuffer, cbsize);
sl@0:
sl@0: // Call SetupDiGetDeviceInterfaceDetail again.
sl@0: // This time, pass a pointer to DetailDataBuffer
sl@0: // and the returned required buffer size.
sl@0:
sl@0: NativeMethods.SetupDiGetDeviceInterfaceDetail
sl@0: (deviceInfoSet,
sl@0: ref myDeviceInterfaceData,
sl@0: detailDataBuffer,
sl@0: bufferSize,
sl@0: ref bufferSize,
sl@0: IntPtr.Zero);
sl@0:
sl@0: // Get the address of the devicePathName.
sl@0:
sl@0: var pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
sl@0:
sl@0: // Get the String containing the devicePathName.
sl@0:
sl@0: devicePathName[memberIndex] = Marshal.PtrToStringAuto(pDevicePathName);
sl@0:
sl@0: if (detailDataBuffer != IntPtr.Zero)
sl@0: {
sl@0: // Free the memory allocated previously by AllocHGlobal.
sl@0:
sl@0: Marshal.FreeHGlobal(detailDataBuffer);
sl@0: }
sl@0: deviceFound = true;
sl@0: }
sl@0: memberIndex = memberIndex + 1;
sl@0: }
sl@0: while (!lastDevice);
sl@0:
sl@0: return deviceFound;
sl@0: }
sl@0: finally
sl@0: {
sl@0: // ***
sl@0: // API function
sl@0:
sl@0: // summary
sl@0: // Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
sl@0:
sl@0: // parameters
sl@0: // DeviceInfoSet returned by SetupDiGetClassDevs.
sl@0:
sl@0: // returns
sl@0: // True on success.
sl@0: // ***
sl@0:
sl@0: if (deviceInfoSet != IntPtr.Zero)
sl@0: {
sl@0: NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
sl@0: }
sl@0: }
sl@0: }
sl@0: }
sl@0: }
sl@0:
sl@0:
sl@0:
sl@0:
sl@0: