#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 Declare Integer SetupDiGetDeviceRegistryProperty In setupapi; Integer DeviceInfoSet,; String @DeviceInfoData,; Integer _Property,; String @PropertyRegDataType,; String @PropertyBuffer,; Integer PropertyBufferSize,; String @RequiredSize **************************************** ** Main PUBLIC devicearray DIMENSION devicearray(1,8) FOR i = 1 TO ALEN(devicearray,2) devicearray(1,i) = [] devicearray(1,1) = 0 ENDFOR ls_HidGuid = SPACE( GUID_Size ) HidD_GetHidGuid( @ls_HidGuid ) *!* GUID_DEVCLASS_PRINTER, 0x4D36E979, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 *!* {4D36E979-E325-11CE-BFC1-08002BE10318} * GUID_DEVCLASS_HIDCLASS, 0x745A17A0, 0x74D3, 0x11D0, 0xB6, 0xFE, 0x00, 0xA0, 0xC9, 0x0F, 0x57, 0xDA #DEFINE GUID_DEVCLASS_HIDCLASS ; CHR(0xA0) + CHR(0x17) + CHR(0x5A) + CHR(0x74) + ; CHR(0xD3) + CHR(0x74) + CHR(0xD0) + CHR(0x11) + ; CHR(0xB6) + CHR(0xFE) + CHR(0x00) + CHR(0xA0) + ; CHR(0xC9) + CHR(0x0F) + CHR(0x57) + CHR(0xDA) #DEFINE GUID_DEVCLASS_PRINTER ; CHR(0x79) + CHR(0xE9) + CHR(0x36) + CHR(0x4D) + ; CHR(0xE3) + CHR(0x25) + CHR(0x11) + CHR(0xCE) + ; CHR(0xBF) + CHR(0xC1) + CHR(0x08) + CHR(0x00) + ; CHR(0x2B) + CHR(0xE1) + CHR(0x03) + CHR(0x18) *!* GUID_DEVCLASS_DISKDRIVE, 0x4d36e967L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 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) *cguid = [{36FC9E60-C465-11CF-8056-444553540000}] *!* GUID_DEVCLASS_USB, 0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ) #DEFINE GUID_DEVCLASS_USB ; CHR(0x60) + CHR(0x9E) + CHR(0xFC) + CHR(0x36) + ; CHR(0x65) + CHR(0xC4) + ; CHR(0xCF) + CHR(0x11) + ; CHR(0x80) + CHR(0x56) + CHR(0x44) + CHR(0x45) + CHR(0x53) + CHR(0x54) + CHR(0x00) + CHR(0x00) *GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED #DEFINE GUID_DEVINTERFACE_USB_DEVICE ; CHR(0x10) + CHR(0xBF) + CHR(0xDC) + CHR(0xA5) + ; CHR(0x30) + CHR(0x65) + ; CHR(0xD2) + CHR(0x11) + ; CHR(0x90) + CHR(0x1F) + CHR(0x00) + CHR(0xC0) + CHR(0x4F) + CHR(0xB9) + CHR(0x51) + CHR(0xED) USBGUID = GUID_DEVINTERFACE_USB_DEVICE *ls_hidGuid = GUID_DEVCLASS_DISKDRIVE *ls_hidGuid = GUID_DEVCLASS_PRINTER *ls_hidGuid = GUID_DEVCLASS_HIDCLASS ls_hidGuid = GUID_DEVINTERFACE_USB_DEVICE *!* lh_DevInfo = SetupDiGetClassDevs( ls_HidGuid, 0, 0, ; *!* DIGCF_PRESENT + DIGCF_DEVICEINTERFACE ) IF !EMPTY( ls_HidGuid ) cGuid = ls_HidGuid cPassValue = DIGCF_PRESENT + DIGCF_DEVICEINTERFACE DO WHILE .T. lldestroy = .F. lh_DevInfo = setupdigetclassdevs(@cGuid, 0, 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 ) EnumerateDevices( lh_DevInfo, cGuid ) 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) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [CLASS: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,2) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_DEVICEDESC) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [DEVICEDESC: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,3) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,4) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,5) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_HARDWAREID) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [HARDWAREID: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,6) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_MFG) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [MFG: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,7) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [PHYSICAL_DEVICE_OBJECT_NAME: ], m.lcDeviceProperty ENDIF 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 ) ********************************************************************************* IF "CREATEFILE" $ UPPER(tc_MESSAGE) * ?"Error using CreateFile with this device." ENDIF * ? 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] m.lcPropertyBuffer = [] ELSE m.lcPropertyBuffer = LEFT(m.lcPropertyBuffer, AT(CHR(0), m.lcPropertyBuffer) - 1) ENDIF RETURN m.lcPropertyBuffer ************************************************************************************** * These values are for future use 00000000 - 7B 34 44 33 36 45 39 37 39 2D 45 33 32 35 2D 31 - {4D36E979-E325-1 00000010 - 31 43 45 2D 42 46 43 31 2D 30 38 30 30 32 42 45 - 1CE-BFC1-08002BE 00000020 - 31 30 33 31 38 7D 00 - 10318}. {4D36E979-E325-11CE-BFC1-08002BE10318} /* f18a0e88-c30c-11d0-8815-00a0c906bed8 */ DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB, 0xf18a0e88, 0xc30c, 0x11d0, 0x88, 0x15, 0x00, \ 0xa0, 0xc9, 0x06, 0xbe, 0xd8); /* A5DCBF10-6530-11D2-901F-00C04FB951ED */ DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \ 0xC0, 0x4F, 0xB9, 0x51, 0xED); /* 3ABF6F2D-71C4-462a-8A92-1E6861E6AF27 */ DEFINE_GUID(GUID_DEVINTERFACE_USB_HOST_CONTROLLER, 0x3abf6f2d, 0x71c4, 0x462a, 0x8a, 0x92, 0x1e, \ 0x68, 0x61, 0xe6, 0xaf, 0x27); /* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */ DEFINE_GUID(GUID_USB_WMI_STD_DATA, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\ 0xA0, 0xC9, 0x59, 0xBB, 0xD2); /* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */ DEFINE_GUID(GUID_USB_WMI_STD_NOTIFICATION, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\ 0xA0, 0xC9, 0x59, 0xBB, 0xD2);