*--Goal: Enumerate all devices and read from/write to USB Device *--Tracy C Holzer - test code *--To do: Replace GetRegistryProperty with SetupDiGetInterfaceDeviceDetail, * get port number from original guid, get handle to it (passing * device name to createfile(), use closehandle to close device, * use deviceiocontrol() generate a CTL_CODE, make command packet, * send using deviceiocontrol() send TXPacket and read from RXPacket * * *References: *http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/device_interface_classes.asp *http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/setupdienumdeviceinterfaces.asp *UT References: UT <B>Re: Pointers in VFP?</B> Thread #1158687 Message #1159601 *Courtesy Christian Ehlscheid *<B>Re: Return handle to device set from SetupDiGetClassDevs</B> Thread #1157607 Message #1157717 *Courtesy Carlos Alloatti ACTIVATE screen CLEAR *--Below is the USB Interface Devices - not necessary for getting all devices * cguid = [{36FC9E60-C465-11CF-8056-444553540000}] cguid = '' && this value passed is ignored when retrieving all classes #Define DIGCF_ALLCLASSES 0x0004 #Define DIGCF_DEVICEINTERFACE 0x0010 #Define DIGCF_PRESENT 0x0002 #Define DIGCF_PROFILE 0x0008 #Define DIGCF_INTERFACEDEVICE DIGCF_DEVICEINTERFACE #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 DECLARE SHORT StrToIntEx IN Shlwapi; STRING pszString, INTEGER dwFlags, INTEGER @pllRet DECLARE INTEGER GetLastError IN kernel32 DECLARE INTEGER SetupDiGetClassDevs IN setupapi.dll ; STRING @cGuid, ; STRING Enumerator, ; INTEGER hwndParent, ; INTEGER nFlags nflags = 0 Enumerator = [] hwndParent = 0 DECLARE INTEGER SetupDiEnumDeviceInterfaces IN setupapi; INTEGER DeviceInfoSet,; STRING @ DeviceInfoData,; STRING @ ByRefterfaceClassGuid,; INTEGER MemberIndex,; STRING @ DeviceInterfaceData 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 sizeof = REPLICATE(' ',2048)+CHR(0) i = 1 nInfo = REPLICATE(' ',2048)+CHR(0) PSP_DEVINFO_DATA = [] lnpointer = 0 LOCAL lcinterfacedata lnx = 0 llDestroy = .F. && needed for cleanup DO WHILE .T. lnpointer = setupdigetclassdevs(@cGuid, NULL, 0, DIGCF_ALLCLASSES) IF TYPE('m.lnpointer') = "N" .AND. m.lnpointer > 0 If m.lnpointer = INVALID_HANDLE_VALUE ? [SetupDiGetClassDevs FAILED] EXIT Endif lldestroy = .T. ? ' Handle to Device Set: ' ?? ALLTRIM(STR(lnpointer)) lndeviceinfoset = lnpointer lnx = 0 && first interface is retrieved by passing 0 m.lnRetVal = -1 iloop = 0 Do While m.lnRetVal <> 0 m.lcDeviceInfoData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lnRetVal = SetupDiEnumDeviceInfo( ; m.lnDeviceInfoSet, ; m.lnx, ; @m.lcDeviceInfoData) IF m.lnRetVal = 0 m.errvalue = getlasterror() ?m.errvalue IF m.errvalue = error_no_more_items EXIT ELSE EXIT ENDIF ELSE IF m.lnRetVal = 1 iloop = 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 ENDIF && increment i for next interface lnx = lnx + 1 ENDIF IF lnx > 10000 && not likely but for testing do NOT go over this EXIT ENDIF ENDDO ELSE ? [SetupDiGetClassDevs FAILED] ENDIF EXIT ENDDO ? 'Found '+ALLTRIM(STR(m.lnx))+' devices.' 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 CLEAR DLLS RETURN ********************************************************************************* 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