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: