#DEFINE MAX_PATH 260 #DEFINE ERROR_NO_MORE_ITEMS 259 #DEFINE INVALID_HANDLE_VALUE -1 #DEFINE DIGCF_DEVICEINTERFACE 0x0010 #DEFINE DIGCF_PRESENT 0x0002 #DEFINE DIGCF_ALLCLASSES 0x0004 #DEFINE GUID_Size 16 #DEFINE SP_DEVICE_INTERFACE_DATA_Size 28 #DEFINE SP_DEVICE_INTERFACE_DETAIL_DATA_Size 5 #Define ERROR_INSUFFICIENT_BUFFER 122 #Define ERROR_NO_MORE_ITEMS 259 #Define INVALID_HANDLE_VALUE -1 #Define SPDRP_ADDRESS 0x001C #Define SPDRP_BUSTYPEGUID 0x0013 #Define SPDRP_CAPABILITIES 0x000F #Define SPDRP_CHARACTERISTICS 0x001B #Define SPDRP_CLASS 0x0007 #Define SPDRP_CLASSGUID 0x0008 #Define SPDRP_COMPATIBLEIDS 0x0002 #Define SPDRP_CONFIGFLAGS 0x000A #Define SPDRP_DEVICE_POWER_DATA 0x000E #Define SPDRP_DEVICEDESC 0x0000 #Define SPDRP_DEVTYPE 0x0019 #Define SPDRP_DRIVER 0x0009 #Define SPDRP_ENUMERATOR_NAME 0x0016 #Define SPDRP_FRIENDLYNAME 0x000C #Define SPDRP_HARDWAREID 0x0001 #Define SPDRP_LOCATION_INFORMATION 0x000D #Define SPDRP_LOWERFILTERS 0x0012 #Define SPDRP_MFG 0x000B #Define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME 0x000E #Define SPDRP_REMOVAL_POLICY 0x001F #Define SPDRP_REMOVAL_POLICY_HW_DEFAULT 0x0020 #Define SPDRP_REMOVAL_POLICY_OVERRIDE 0x0021 #Define SPDRP_SECURITY 0x0017 #Define SPDRP_SECURITY_SDS 0x0018 #Define SPDRP_SERVICE 0x0004 #Define SPDRP_UI_NUMBER 0x0010 #Define SPDRP_UI_NUMBER_DESC_FORMAT 0x001E #Define SPDRP_UPPERFILTERS 0x0011 #Define INVALID_HANDLE_VALUE -1 #DEFINE ERROR_NO_MORE_ITEMS 259 #DEFINE ERROR_INVALID_PARAMETER 87 #DEFINE ERROR_INVALID_FLAGS 1004 #DEFINE ERROR_INSUFFICIENT_BUFFER 122 #DEFINE DIGCF_INTERFACEDEVICE 16 && 0x00000010 #DEFINE DIGCF_PRESENT 2 && 0x00000002 #define DIGCF_ALLCLASSES 4 LOCAL ls_GUID, lh_DevInfo PRIVATE iLoop, llOnce iLoop = 0 llOnce = .F. DECLARE LONG GetLastError IN Kernel32 DECLARE LONG CloseHandle IN Kernel32 LONG hObject DECLARE LONG CreateFile IN Kernel32 ; STRING cFileName, LONG dwDesiredAccess, LONG dwShareMode, ; STRING @ lpSecurityAttributes, LONG dwCreationDisposition, ; LONG dwFlagsAndAttributes, LONG hTemplateFile DECLARE HidD_GetHidGuid IN HID ; STRING @ O_sHidGuid DECLARE LONG HidD_GetProductString IN HID ; LONG hHidDeviceObject, STRING @ O_cBuffer, LONG nBufferLength DECLARE LONG SetupDiDestroyDeviceInfoList IN SetupAPI ; LONG hDeviceInfoSet DECLARE LONG SetupDiGetClassDevs IN SetupAPI ; STRING @ sGUID, STRING Enumerator, LONG nhWnd, LONG nFlags DECLARE LONG SetupDiEnumDeviceInterfaces IN SetupAPI ; LONG hDeviceInfo, STRING @ sDeviceInfoData, ; STRING @ sInterfaceClassGuid, LONG MemberIndex, ; STRING @ O_sDeviceInterfaceData DECLARE LONG SetupDiGetDeviceInterfaceDetail IN SetupAPI ; LONG hDeviceInfo, STRING @ sDeviceInterfaceData, ; STRING @ O_sDeviceInterfaceDetailData, LONG DeviceInterfaceDetailDataSize, ; LONG @ O_nRequiredSize, STRING @ O_sDeviceInfoData DECLARE INTEGER SetupDiEnumDeviceInfo IN setupapi; INTEGER DeviceInfoSet,; INTEGER MemberIndex,; STRING @DeviceInfoData **************************************** ** Main ls_HidGuid = SPACE( GUID_Size ) HidD_GetHidGuid( @ls_HidGuid ) #DEFINE GUID_DEVCLASS_PRINTER ; CHR(0x4D) + CHR(0x36) + CHR(0xE9) + CHR(0x79) + ; CHR(0xE3) + CHR(0x25) + CHR(0x11) + CHR(0xCE) + ; CHR(0xBF) + CHR(0xC1) + CHR(0x08) + CHR(0x00) + ; CHR(0x2B) + CHR(0xE1) + CHR(0x03) + CHR(0x18) #DEFINE GUID_DEVCLASS_DISKDRIVE ; CHR(0x67) + CHR(0xE9) + CHR(0x36) + CHR(0x4D) + ; CHR(0x25) + CHR(0xE3) + ; CHR(0xCE) + CHR(0x11) + ; CHR(0xBF) + CHR(0xC1) + CHR(0x08) + CHR(0x00) + CHR(0x2B) + CHR(0xE1) + CHR(0x03) + CHR(0x18) *ls_hidGuid = GUID_DEVCLASS_DISKDRIVE IF !EMPTY( ls_HidGuid ) * lh_DevInfo = SetupDiGetClassDevs( ls_HidGuid, 0, 0, ; DIGCF_PRESENT + DIGCF_DEVICEINTERFACE ) cGuid = ls_HidGuid cPassValue = DIGCF_ALLCLASSES DO WHILE .T. lldestroy = .F. lh_DevInfo = setupdigetclassdevs(@cGuid, NULL, 0, cPassValue) m.lnpointer = lh_DevInfo IF TYPE('m.lnpointer') <> "N" .OR. m.lnpointer = INVALID_HANDLE_VALUE ? [SetupDiGetClassDevs FAILED] EXIT Endif lldestroy = .T. lndeviceinfoset = lnpointer * lh_DevInfo = SetupDiGetClassDevs( ls_HidGuid, 0, 0, ; * DIGCF_ALLCLASSES) IF (lh_DevInfo != INVALID_HANDLE_VALUE) CLEAR EnumerateDevices( lh_DevInfo, ls_HidGuid ) IF SetupDiDestroyDeviceInfoList( lh_DevInfo ) <> 0 lldestroy = .F. ENDIF IF cPassValue == DIGCF_ALLCLASSES EXIT ENDIF ELSE EXIT ENDIF ENDDO ENDIF IF lldestroy *--Cleanup ?'==================================================' ?'Cleaning Up...' DECLARE INTEGER SetupDiDestroyDeviceInfoList IN setupapi; INTEGER DeviceInfoSet llokay = SetupDiDestroyDeviceInfoList(lnpointer) ?' Releasing the handle - SetupDiDestroyDeviceInfoList Result: ' ?? llokay ?' Last Error: ' ?? GetLastError() ENDIF IF !llOnce ?"***********************************************************" ?" Error Using SetupDiEnumDeviceInterfaces ---------->>>>>>>>" ?"***********************************************************" ENDIF RETURN * Clear Dlls ********************************************************************************* ** Procedures ********************************************************************************* ********************************************************************************* PROCEDURE EnumerateDevices( th_DevInfo, ts_Guid ) ********************************************************************************* LOCAL ls_DiData, ls_DiDetailData, lh_Device LOCAL ln_Error, ln_Index, ln_ReqSize LOCAL lc_DeviceName, lw_Buffer, lc_Buffer STORE 0 TO ln_Error, ln_Index, ln_ReqSize ls_DiData = PADR( BINTOC( SP_DEVICE_INTERFACE_DATA_Size, '4rs' ), ; SP_DEVICE_INTERFACE_DATA_Size, CHR(0) ) m.lnRetVal = -1 m.lnRetVal2 = -1 iloop = 0 Do While (m.lnRetVal <> 0 .or. m.lnRetVal2 <> 0) *.and. (ln_Error != ERROR_NO_MORE_ITEMS) m.lcDeviceInfoData = PADR(BINTOC(28, [4RS]), 4, CHR(0)) + REPLICATE(CHR(0), 24) m.lnDeviceInfoSet = th_DevInfo m.lnRetVal2 = SetupDiEnumDeviceInfo( ; th_DevInfo, ; iLoop, ; @m.lcDeviceInfoData) lifoundit = .F. iLoop = iLoop + 1 IF m.lnRetVal2 <> 0 lifoundit = .T. m.lnx = iLoop - 1 DIMENSION devicearray(iLoop,8) &&& extract the interface data here ... (CTOBIN, SUBSTR) devicearray(m.iLoop,1) = m.lnx ?[Device: ], m.lnx m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_CLASS) ?[Property:], [CLASS: ], m.lcDeviceProperty devicearray(m.iLoop,2) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_DEVICEDESC) ?[Property:], [DEVICEDESC: ], m.lcDeviceProperty devicearray(m.iLoop,3) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME) ?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty devicearray(m.iLoop,4) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME) ?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty devicearray(m.iLoop,5) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_HARDWAREID) ?[Property:], [HARDWAREID: ], m.lcDeviceProperty devicearray(m.iLoop,6) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_MFG) ?[Property:], [MFG: ], m.lcDeviceProperty devicearray(m.iLoop,7) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) ?[Property:], [PHYSICAL_DEVICE_OBJECT_NAME: ], m.lcDeviceProperty devicearray(m.iLoop,8) = m.lcDeviceProperty ?"*****************************************************" ?" Success using SetupDiGetDeviceRegistryProperty" ?"*****************************************************" ENDIF m.lnRetVal = SetupDiEnumDeviceInterfaces( th_DevInfo, 0, ts_Guid, ln_Index, @ls_DiData ) IF m.lnRetVal == 0 ln_Error = GetLastError() IF (ln_Error != ERROR_NO_MORE_ITEMS) ShowError( ln_Error, ln_Index, 'SetupDiEnumDeviceInterfaces()' ) ELSE ? [ No More Devices] ENDIF IF lifoundit ln_Index = ln_Index + 1 LOOP EXIT ENDIF ELSE llOnce = .T. && SetupDiEnumDeviceInterfaces worked at least once SetupDiGetDeviceInterfaceDetail( th_DevInfo, ls_DiData, ; 0, 0, @ln_ReqSize, 0 ) ls_DiDetailData = PADR( BINTOC( SP_DEVICE_INTERFACE_DETAIL_DATA_Size, '4rs' ), ; ln_ReqSize, CHR(0) ) ln_Result = SetupDiGetDeviceInterfaceDetail( th_DevInfo, ls_DiData, ; @ls_DiDetailData, ln_ReqSize, @ln_ReqSize, 0 ) IF (ln_Result == 1) lc_DeviceName = SUBSTR( ls_DiDetailData, 5 ) ln_Pos = AT( CHR(0), lc_DeviceName ) IF (ln_Pos > 0) lc_DeviceName = LEFT( lc_DeviceName, ln_Pos - 1 ) ENDIF ?lc_DeviceName lh_Device = CreateFile( lc_DeviceName, 0x80000000, 0x1, 0, 3, 0x20000000, 0 ) IF (lh_Device != INVALID_HANDLE_VALUE) lw_Buffer = SPACE( MAX_PATH ) IF (HidD_GetProductString( lh_Device, @lw_Buffer, MAX_PATH ) == 1) lc_Buffer = MakeANSI( lw_Buffer ) ? 'Product Name: ' + lc_Buffer ENDIF CloseHandle( lh_Device ) ELSE ShowError( GetLastError(), ln_Index, 'CreateFile()' ) ENDIF ELSE ShowError( GetLastError(), ln_Index, 'SetupDiGetDeviceInterfaceDetail()' ) ENDIF ln_Index = ln_Index + 1 ENDIF ENDDO ENDPROC RETURN ********************************************************************************* PROCEDURE ShowError( tn_Error, tn_Index, tc_Message ) ********************************************************************************* ? tc_Message + ' ERROR !!' IF (VARTYPE( tn_Index ) == 'N') ? 'Member index:', tn_Index ENDIF ? 'Error No:', tn_Error ENDPROC ********************************************************************************* PROCEDURE MakeANSI( tw_String ) ********************************************************************************* LOCAL lc_String, ln_Pos lc_String = STRCONV( STRCONV( tw_String, 6 ), 2 ) ln_Pos = AT( CHR(0), lc_String ) IF (ln_Pos > 0) lc_String = LEFT( lc_String, ln_Pos - 1 ) ENDIF RETURN lc_String ENDPROC ********************************************************************************* PROCEDURE GetRegistryProperty ********************************************************************************* LPARAMETERS tnDeviceInfoSet, tcDeviceInfoData, tnProperty LOCAL lnRetVal, lcPropertyBuffer, lcRequiredSize m.lcPropertyBuffer = SPACE(0) m.lcRequiredSize = SPACE(4) m.PropertyRegDataType = SPACE(4) *!* "The SetupDiGetDeviceRegistryProperty function retrieves the specified device property." *!* We don't know the size of the required string buffer for the property until we call the *!* function, so we first call it with a null string to get the required buffer size, then *!* we call again with the proper buffer size m.lnRetVal = SetupDiGetDeviceRegistryProperty( ; m.tnDeviceInfoSet, ; @m.tcDeviceInfoData, ; m.tnProperty, ; @m.PropertyRegDataType, ; @m.lcPropertyBuffer, ; LEN(m.lcPropertyBuffer), ; @m.lcRequiredSize) IF m.lnRetVal = 0 AND GetLastError() = ERROR_INSUFFICIENT_BUFFER THEN m.lcPropertyBuffer = SPACE(CTOBIN(m.lcRequiredSize, [4RS])) m.lnRetVal = SetupDiGetDeviceRegistryProperty( ; m.tnDeviceInfoSet, ; @m.tcDeviceInfoData, ; m.tnProperty, ; 0, ; @m.lcPropertyBuffer, ; LEN(m.lcPropertyBuffer), ; @m.lcRequiredSize) ENDIF IF m.lnRetVal = 0 THEN ? [SetupDiGetDeviceRegistryProperty ERROR] m.lcPropertyBuffer = [SetupDiGetDeviceRegistryProperty ERROR] ELSE m.lcPropertyBuffer = LEFT(m.lcPropertyBuffer, AT(CHR(0), m.lcPropertyBuffer) - 1) ENDIF RETURN m.lcPropertyBuffer