/// <summary> /// Uses SetupDi API functions to retrieve the device path name of an /// attached device that belongs to an interface class. /// </summary> /// /// <param name="myGuid"> an interface class GUID. </param> /// <param name="devicePathName"> a pointer to an array of strings that /// will contain the device path names of attached devices. </param> /// /// <returns> /// True if at least one device is found, False if not. /// </returns> public Boolean FindDeviceFromGuid(System.Guid myGuid, ref String[] devicePathName) { String apiFunction = ""; Boolean deviceFound = false; IntPtr deviceInfoSet = new System.IntPtr(); bool is64Bit = false; Boolean lastDevice = false; Int32 bufferSize = 0; Int32 memberIndex = 0; SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new DeviceManagement.SP_DEVICE_INTERFACE_DATA(); SP_DEVICE_INTERFACE_DETAIL_DATA MyDeviceInterfaceDetailData = new DeviceManagement.SP_DEVICE_INTERFACE_DETAIL_DATA(); Boolean result = false; Boolean success = false; try { if (System.IntPtr.Size == 8) is64Bit = true; // *** // 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. // *** deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); apiFunction = "SetupDiClassDevs"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); deviceFound = false; 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. // Alternative for 32-bit code: // MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData); if (!is64Bit) { MyDeviceInterfaceData.cbSize = 28; } else { MyDeviceInterfaceData.cbSize = 32; } // *** // 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 = SetupDiEnumDeviceInterfaces(deviceInfoSet, 0, ref myGuid, memberIndex, ref MyDeviceInterfaceData); apiFunction = "SetupDiEnumDeviceInterfaces"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); // Find out if a device information set was retrieved. if ((result == false)) { lastDevice = true; } else { // A device is present. Debug.WriteLine(" DeviceInfoSet for device #" + Convert.ToString(memberIndex) + ": "); Debug.WriteLine(" cbSize = " + Convert.ToString(MyDeviceInterfaceData.cbSize)); Debug.WriteLine(" InterfaceclassGuid = " + MyDeviceInterfaceData.InterfaceClassGuid.ToString()); Debug.WriteLine(" Flags = " + Convert.ToString(MyDeviceInterfaceData.Flags, 16)); // *** // 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. // *** //MyDeviceInterfaceDetailData = ( ( DeviceManagement.SP_DEVICE_INTERFACE_DETAIL_DATA )( null ) ); success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero); apiFunction = "SetupDiGetDeviceInterfaceDetail"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); Debug.WriteLine(" (OK to say too small)"); Debug.WriteLine(" Required buffer size for the data: " + bufferSize); // Store the structure's size. MyDeviceInterfaceDetailData.cbSize = Marshal.SizeOf(MyDeviceInterfaceDetailData); // Allocate memory for the MyDeviceInterfaceDetailData Structure using the returned buffer size. IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize); // Store cbSize in the first 4 bytes of the array if (!is64Bit) { Marshal.WriteInt32(detailDataBuffer, 4 + Marshal.SystemDefaultCharSize); } else { Marshal.WriteInt32(detailDataBuffer, 8); } Debug.WriteLine("cbsize = " + MyDeviceInterfaceDetailData.cbSize); // Call SetupDiGetDeviceInterfaceDetail again. // This time, pass a pointer to DetailDataBuffer // and the returned required buffer size. success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero); apiFunction = " Result of second call: "; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); Debug.WriteLine(" MyDeviceInterfaceDetailData.cbSize: " + Convert.ToString(MyDeviceInterfaceDetailData.cbSize)); // 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); Debug.WriteLine("Device Path = " + devicePathName[memberIndex]); Debug.WriteLine("Device Path Length= " + devicePathName[memberIndex].Length); // Free the memory allocated previously by AllocHGlobal. Marshal.FreeHGlobal(detailDataBuffer); deviceFound = true; } memberIndex = memberIndex + 1; } while (!lastDevice == true); // Trim the array to the number of devices found. String[] tempArray = new String[memberIndex - 1]; System.Array.Copy(devicePathName, tempArray, Math.Min(devicePathName.Length, tempArray.Length)); devicePathName = tempArray; Debug.WriteLine("Number of HIDs found = " + Convert.ToString(memberIndex - 1)); // *** // 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. // *** SetupDiDestroyDeviceInfoList(deviceInfoSet); apiFunction = "DestroyDeviceInfoList"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); return deviceFound; } catch (Exception ex) { DisplayException( MODULE_NAME, ex ); throw ; } }
/// <summary> /// Uses SetupDi API functions to retrieve the device path name of an /// attached device that belongs to an interface class. /// </summary> /// /// <param name="myGuid"> an interface class GUID. </param> /// <param name="devicePathName"> a pointer to an array of strings that /// will contain the device path names of attached devices. </param> /// /// <returns> /// True if at least one device is found, False if not. /// </returns> public Boolean FindDeviceFromGuid(System.Guid myGuid, ref String[] devicePathName) { String apiFunction = ""; Boolean deviceFound = false; IntPtr deviceInfoSet = new System.IntPtr(); bool is64Bit = false; Boolean lastDevice = false; Int32 bufferSize = 0; Int32 memberIndex = 0; SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new DeviceManagement.SP_DEVICE_INTERFACE_DATA(); SP_DEVICE_INTERFACE_DETAIL_DATA MyDeviceInterfaceDetailData = new DeviceManagement.SP_DEVICE_INTERFACE_DETAIL_DATA(); Boolean result = false; Boolean success = false; try { if (System.IntPtr.Size == 8) { is64Bit = true; } // *** // 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. // *** deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); apiFunction = "SetupDiClassDevs"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); deviceFound = false; 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. // Alternative for 32-bit code: // MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData); if (!is64Bit) { MyDeviceInterfaceData.cbSize = 28; } else { MyDeviceInterfaceData.cbSize = 32; } // *** // 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 = SetupDiEnumDeviceInterfaces(deviceInfoSet, 0, ref myGuid, memberIndex, ref MyDeviceInterfaceData); apiFunction = "SetupDiEnumDeviceInterfaces"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); // Find out if a device information set was retrieved. if ((result == false)) { lastDevice = true; } else { // A device is present. Debug.WriteLine(" DeviceInfoSet for device #" + Convert.ToString(memberIndex) + ": "); Debug.WriteLine(" cbSize = " + Convert.ToString(MyDeviceInterfaceData.cbSize)); Debug.WriteLine(" InterfaceclassGuid = " + MyDeviceInterfaceData.InterfaceClassGuid.ToString()); Debug.WriteLine(" Flags = " + Convert.ToString(MyDeviceInterfaceData.Flags, 16)); // *** // 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. // *** //MyDeviceInterfaceDetailData = ( ( DeviceManagement.SP_DEVICE_INTERFACE_DETAIL_DATA )( null ) ); success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero); apiFunction = "SetupDiGetDeviceInterfaceDetail"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); Debug.WriteLine(" (OK to say too small)"); Debug.WriteLine(" Required buffer size for the data: " + bufferSize); // Store the structure's size. MyDeviceInterfaceDetailData.cbSize = Marshal.SizeOf(MyDeviceInterfaceDetailData); // Allocate memory for the MyDeviceInterfaceDetailData Structure using the returned buffer size. IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize); // Store cbSize in the first 4 bytes of the array if (!is64Bit) { Marshal.WriteInt32(detailDataBuffer, 4 + Marshal.SystemDefaultCharSize); } else { Marshal.WriteInt32(detailDataBuffer, 8); } Debug.WriteLine("cbsize = " + MyDeviceInterfaceDetailData.cbSize); // Call SetupDiGetDeviceInterfaceDetail again. // This time, pass a pointer to DetailDataBuffer // and the returned required buffer size. success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero); apiFunction = " Result of second call: "; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); Debug.WriteLine(" MyDeviceInterfaceDetailData.cbSize: " + Convert.ToString(MyDeviceInterfaceDetailData.cbSize)); // 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); Debug.WriteLine("Device Path = " + devicePathName[memberIndex]); Debug.WriteLine("Device Path Length= " + devicePathName[memberIndex].Length); // Free the memory allocated previously by AllocHGlobal. Marshal.FreeHGlobal(detailDataBuffer); deviceFound = true; } memberIndex = memberIndex + 1; }while (!lastDevice == true); // Trim the array to the number of devices found. String[] tempArray = new String[memberIndex - 1]; System.Array.Copy(devicePathName, tempArray, Math.Min(devicePathName.Length, tempArray.Length)); devicePathName = tempArray; Debug.WriteLine("Number of HIDs found = " + Convert.ToString(memberIndex - 1)); // *** // 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. // *** SetupDiDestroyDeviceInfoList(deviceInfoSet); apiFunction = "DestroyDeviceInfoList"; Debug.WriteLine(MyDebugging.ResultOfAPICall(apiFunction)); return(deviceFound); } catch (Exception ex) { DisplayException(MODULE_NAME, ex); return(false); } }