>#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); >