CLEAR CLOSE ALL CLEAR ALL IF !FILE('testusb.dbf') CREATE TABLE testusb (cvalue c(250)) ELSE USE testusb ENDIF *!* #define IOCTL_USBPRINT_VENDOR_SET_COMMAND CTL_CODE(FILE_DEVICE_UNKNOWN, *!* 14, *!* METHOD_BUFFERED, *!* FILE_ANY_ACCESS) *#define IOCTL_USBPRINT_VENDOR_GET_COMMAND CTL_CODE(FILE_DEVICE_UNKNOWN, * 15, * METHOD_BUFFERED, * FILE_ANY_ACCESS) *CTL_CODE = DeviceType * 65536 + Function * 4 + Method + Access * 16384 #define FILE_DEVICE_UNKNOWN 0x00000022 #define METHOD_BUFFERED 0 #define FILE_ANY_ACCESS 0 #DEFINE GET_SERIAL_NUMBER 1575952 #DEFINE VENDOR_GET 222964 #DEFINE VENDOR_SET 222960 *Serial Number *!* 24 * 65536 + 772 * 4 + 0 + 0 * 16384 *!* 24 * 65536 + 772 * 4 *!* (24*65536) + (772*4) *!* 1572864 + 3088 *!* = 1575952, or 0x00180C10 *Vendor Get Command *!* 34 * 65536 + 15 * 4 + 0 + 0 * 16384 *!* 34 * 65536 + 15 * 4 *!* (34*65536) + (15*4) *!* 222904 + 60 *!* = 222964, or 0x00366F4 *Vendor Set Command *!* 34 * 65536 + 14 * 4 + 0 + 0 * 16384 *!* 34 * 65536 + 14 * 4 *!* (34*65536) + (14*4) *!* 222904 + 56 *!* = 222960, or 0x00366F0 CLEAR *#DEFINE IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 0x0304 *CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS) *#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ * ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ #DEFINE GENERIC_READ 0x80000000 #DEFINE GENERIC_WRITE 0x40000000 #DEFINE FILE_SHARE_READ 1 && 0x00000001 #DEFINE FILE_SHARE_WRITE 2 && 0x00000002 #DEFINE OPEN_ALWAYS 4 #DEFINE OPEN_EXISTING 3 #DEFINE CREATE_ALWAYS 2 #DEFINE CREATE_NEW 1 #DEFINE TRUNCATE_EXISTING 5 #DEFINE FILE_ATTRIBUTE_NORMAL 0x80 && 0x00000080 #DEFINE FILE_FLAG_SEQUENTIAL_SCAN 0x08000000 #DEFINE FILE_FLAG_OVERLAPPED 0x40000000 #DEFINE FILE_FLAG_WRITE_THROUGH 0x80000000 #DEFINE FILE_FLAG_RANDOM_ACCESS 0x10000000 #DEFINE MAX_PATH 255 #DEFINE ERROR_NO_MORE_ITEMS 259 #DEFINE ERROR_GEN_FAILURE 31 && device is not responding #DEFINE ERROR_WRITE_FAULT 29 && cannot write to specified device #DEFINE ERROR_READ_FAULT 30 && cannot read from specified device #DEFINE ERROR_OUT_OF_PAPER 28 && printer is out of paper #DEFINE ERROR_NOT_SUPPORTED 50 && The request is not supported #DEFINE INVALID_HANDLE_VALUE -1 #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 All devices which expose interfaces #DEFINE DIGCF_PRESENT 2 && 0x00000002 All installed devices present currently #DEFINE DIGCF_ALLCLASSES 4 && All installed devices #DEFINE DIGCF_PROFILE 8 && All devices part of current hardware profile #DEFINE DIGCF_DEVICEINTERFACE 0x0010 && 0x00000010 All devices which expose interfaces LOCAL ls_GUID, m.ln_Pointer PRIVATE iLoop, llOnce, lnRW420, lnRW420ID, lcSendValue, lcReceiveValue lnRW420 = .F. && RW420 Printer found lnRW420ID = 0 && if greater than zero, this is our printer to write data to iLoop = 0 llOnce = .F. lcSendValue = SPACE(255) lcReceiveValue = SPACE(255) 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 INTEGER WriteFile IN kernel32; INTEGER UsbHandle,; STRING lpBuffer,; INTEGER lnumbytes,; INTEGER @ BytesWritten,; INTEGER lpOverlapped DECLARE HidD_GetHidGuid IN HID ; STRING @ O_sHidGuid DECLARE LONG HidD_GetProductString IN HID ; LONG hHidDeviceObject, STRING @ O_cBuffer, LONG nBufferLength DECLARE LONG HidD_GetAttributes IN HID ; LONG hHidDeviceObject, STRING @ _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 DECLARE INTEGER ReadFile IN kernel32; INTEGER hFile,; STRING @lpBuffer,; INTEGER nNumberOfBytesToRead,; INTEGER @lpNumberOfBytesRead,; STRING lpOverlapped DECLARE INTEGER FormatMessage IN kernel32; INTEGER dwFlags, INTEGER lpSource, INTEGER dwMessageId,; INTEGER dwLanguageId, INTEGER @lpBuffer,; INTEGER nSize, INTEGER Arguments DECLARE RtlMoveMemory IN kernel32 As CopyMemory; STRING @Destination, INTEGER Source, INTEGER nLength DECLARE INTEGER DeviceIoControl IN kernel32 ; INTEGER hDevice,; INTEGER dwIoControlCode,; STRING @ lpInBuffer,; INTEGER nInBufferSize,; STRING @ lpOutBuffer,; INTEGER nOutBufferSize,; INTEGER lpBytesReturned,; STRING @ lpOverlapped * ADD GetQueuedCompletionStatus() *---------------------------------------------------------------------------------------------------- *--Main Program *---------------------------------------------------------------------------------------------------- PUBLIC devicearray && Used for storing all device information from registry DIMENSION devicearray(1,10) FOR i = 1 TO ALEN(devicearray,2) devicearray(1,i) = [] devicearray(1,1) = 0 ENDFOR lc_Guid = SPACE( GUID_Size ) && Guid variable *HidD_GetHidGuid( @ls_HidGuid ) && Get the device interface GUID for the the HIDClass devices *--Device Classes and Device Interface Classes (Device Interface Class needed for SetupDiEnumDeviceInterfaces() * 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) *!* GUID_DEVCLASS_PRINTER, 0x4D36E979, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 *!* [{4D36E979-E325-11CE-BFC1-08002BE10318}] #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) *!* GUID_DEVCLASS_USB, 0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ) * [{36FC9E60-C465-11CF-8056-444553540000}] #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) * A5DCBF10-6530-11D2-901F-00C04FB951ED */ *!* RW420: *!* USB\Vid_0a5f&Pid_003e&Rev_0001 *!* USB\Vid_0a5f&Pid_003e *HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{28d78fad-5a12-11d1-ae5b-0000f803a8c2} *{28d78fad-5a12-11d1-ae5b-0000f803a8c2 #DEFINE GUID_DEVINTERFACE_USB_PRINT ; CHR(0xad) + CHR(0x8f) + CHR(0xd7) + CHR(0x28) + ; CHR(0x12) + CHR(0x5a) + ; CHR(0xd1) + CHR(0x11) + ; CHR(0xae) + CHR(0x5b) + CHR(0x00) + CHR(0x00) + CHR(0xf8) + CHR(0x03) + CHR(0xa8) + CHR(0xc2) *--Store the device guid we want to use to lc_Guid for use *lc_Guid = GUID_DEVINTERFACE_USB_DEVICE lc_Guid = GUID_DEVINTERFACE_USB_PRINT *lc_Guid = GUID_DEVCLASS_PRINTER IF !EMPTY( lc_Guid ) * cFlags = DIGCF_PRESENT + DIGCF_DEVICEINTERFACE && all classes present that expose interfaces * cFlags = DIGCF_ALLCLASSES *^^TCH cFlags = DIGCF_DEVICEINTERFACE DO WHILE .T. && a loop not really need for this test but here for later lldestroy = .F. *--Retrieve a device information set that contains all the devices of a specified class *--The Class is determined by the interface class guid passed in lc_Guid m.ln_Pointer = SetupDiGetClassDevs(@lc_Guid, 0, 0, cFlags) IF TYPE('m.ln_Pointer') <> "N" .OR. m.ln_Pointer = INVALID_HANDLE_VALUE ? [SetupDiGetClassDevs FAILED] EXIT ENDIF lldestroy = .T. lndeviceinfoset = m.ln_pointer IF (m.ln_Pointer != INVALID_HANDLE_VALUE) CLEAR ? [Pointer: ]+ALLTRIM(STR(m.ln_pointer)) EnumerateDevices( m.ln_Pointer, lc_Guid ) *--Destroy the device information list and free all associated memory IF SetupDiDestroyDeviceInfoList( m.ln_Pointer ) <> 0 lldestroy = .F. ENDIF EXIT ELSE EXIT ENDIF ENDDO ENDIF IF lldestroy *--Cleanup *--Destroy the device information list and free all associated memory ?'==================================================' ?'Cleaning Up...' DECLARE INTEGER SetupDiDestroyDeviceInfoList IN setupapi; INTEGER DeviceInfoSet llokay = SetupDiDestroyDeviceInfoList(m.ln_Pointer) ?' Releasing the handle - SetupDiDestroyDeviceInfoList Result: ' ?? llokay ?' Last Error: ' ?? GetLastError() ENDIF IF !llOnce ?"***********************************************************" ?" Error Using SetupDiEnumDeviceInterfaces ---------->>>>>>>>" ?"***********************************************************" ENDIF CLEAR DLLS RETURN ********************************************************************************* ** Procedures ********************************************************************************* ********************************************************************************* PROCEDURE EnumerateDevices( th_DevInfo, ts_Guid ) ********************************************************************************* LOCAL ls_DiData, ls_DiDetailData, lh_Device LOCAL ln_Error, ln_Index, ln_ReqSize, ln_Error1 LOCAL lc_DeviceName, lw_Buffer, lc_Buffer STORE 0 TO ln_Error, ln_Error1, ln_Index, ln_ReqSize ls_DiData = PADR( BINTOC( SP_DEVICE_INTERFACE_DATA_Size, '4rs' ), ; SP_DEVICE_INTERFACE_DATA_Size, CHR(0) ) m.lnRetVal = -1 && SetupDiEnumDeviceInterfaces m.lnRetVal2 = -1 && SetupDiEnumDeviceInfo iLoop = 0 DO WHILE (m.lnRetVal <> 0 .OR. m.lnRetVal2 <> 0 .or. ln_Error != ERROR_NO_MORE_ITEMS) *-- Use SetupDiEnumDeviceInfo function to return a SP_DEVINFO_DATA structure *-- that specifies a device information element in a device information set. 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) ln_Error = GetLastError() IF m.lnRetVal2 = 0 .and. ln_Error = ERROR_NO_MORE_ITEMS EXIT ENDIF lifoundit = .F. iLoop = iLoop + 1 llrw420 = .F. llInterface = .F. IF m.lnRetVal2 <> 0 *--Retrieve the specified device property from the registry lifoundit = .T. m.lnx = iLoop - 1 DIMENSION devicearray(iLoop,10) &&& extract the interface data here ... (CTOBIN, SUBSTR) devicearray(m.iLoop,1) = m.lnx ?[->Device: ], ALLTRIM(STR(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:], [DEVICE DESC: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,3) = m.lcDeviceProperty IF TYPE('m.lcDeviceProperty') = "C" .and. "USB PRINT" $ UPPER(m.lcDeviceProperty) lnRW420 = .T. lnRW420ID = m.lnx ENDIF 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 IF TYPE('m.lcDeviceProperty') = "C" .and. ('USB' $ m.lcDeviceProperty .or. UPPER(ALLTRIM(m.lcDeviceProperty)) == "USB") *--Use the USB Interface GUID to get the device interface details ts_Guid = GUID_DEVINTERFACE_USB_DEVICE ENDIF 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 IF TYPE('m.lcDeviceProperty') = "C" .and. "0a5f&pid_003e" $ LOWER(m.lcDeviceProperty) llrw420 = .T. && Printer lnRW420 = .T. lnRW420ID = m.lnx ENDIF IF TYPE('m.lcDeviceProperty') = "C" .and. "ZEBRA_RW_420" $ UPPER(m.lcDeviceProperty) llrw420 = .T. && USB lnRW420 = .T. lnRW420ID = m.lnx ENDIF 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 m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_DEVTYPE ) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [DEV TYPE: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,9) = m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_CLASSGUID) IF ! ("ERROR" $ m.lcDeviceProperty) ?[Property:], [CLASS GUID: ], m.lcDeviceProperty ENDIF devicearray(m.iLoop,10) = m.lcDeviceProperty IF TYPE('m.lcDeviceProperty') = "C" .and. UPPER(ALLTRIM(m.lcDeviceProperty)) = [{36FC9E60-C465-11CF-8056-444553540000}] *--USB ts_Guid = GUID_DEVINTERFACE_USB_DEVICE ENDIF *!* ?"*****************************************************" *!* ?" Success using SetupDiGetDeviceRegistryProperty" *!* ?"*****************************************************" ELSE ?" NO data from SetupDiEnumDeviceInfo or SetupDiGetDeviceRegistryProperty" ENDIF *^^Tch lc_TName = [\\?\usb#Vid_0a5f&Pid_003e#XXRC06-21-5631#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}] =getvaluesfromdevice(lc_TName) ?usbinfo(lc_TName) *--Retrieve a context structure for a device interface of the device information set *--Each call returns information about one device interface. *--Call repeatedly to get information about several interfaces exposed by one or more devices m.lnRetVal = SetupDiEnumDeviceInterfaces( th_DevInfo, 0, ts_Guid, ln_Index, @ls_DiData ) IF m.lnRetVal == 0 ln_Error1 = GetLastError() IF (ln_Error1 != ERROR_NO_MORE_ITEMS) ShowError( ln_Error1, ln_Index, 'SetupDiEnumDeviceInterfaces()' ) ELSE IF llOnce ? [ No More Devices from SetupDiEnumDeviceInterfaces] ELSE ? [ No Devices from SetupDiEnumDeviceInterfaces] ENDIF ENDIF IF llrw420 .and. lnRW420ID > 0 FOR icheckitems = 2 TO 10 IF icheckitems > ALEN(devicearray,2) EXIT ENDIF lc_deviceName = devicearray(m.iLoop,icheckitems) IF TYPE('lc_DeviceName') = "N" lc_DeviceName = ALLTRIM(STR(lc_DeviceName)) ELSE IF TYPE('lc_DeviceName') <> "C" lc_DeviceName = '' ENDIF lc_DeviceName = ALLTRIM(lc_devicename) ENDIF lc_DeviceName = STRTRAN(lc_DeviceName,CHR(0),'') ? [Trying: ],ALLTRIM(STR(icheckitems))+[ of 10 ], lc_DeviceName lh_Device = CreateFile(lc_DeviceName, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) IF (lh_Device != INVALID_HANDLE_VALUE) && Can use DeviceIoControl From Lh_Device also lw_Buffer = SPACE( MAX_PATH ) *--Is it a HID? Get Attributes - Deal with this later IF (HidD_GetAttributes( lh_Device, @lw_Buffer, MAX_PATH ) == 1) lc_Buffer = STRTRAN(lw_buffer,CHR(0),'') ? 'Information: ' + lc_Buffer ELSE ? [No HID Information] ENDIF *--Is it a HID? Get Product Name - Deal with this later 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 IF lnRW420 .and. lnRW420ID > 0 *--Will DeviceIoControl Work? lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13) lnWritten = 0 IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure lnRW420 = .F. lnRW420ID = 0 lcReadBuffer = REPLICATE(" ",MAX_PATH) lnBytesReturned = 0 lnCounter2 = 0 DO WHILE lnBytesReturned == 0 lncounter2 = lncounter2 + 1 IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, NULL) <> 0 lncounter = 0 DO WHILE lncounter < 50 lncounter = lncounter + 1 DOEVENTS IF !EMPTY(MakeANSI(lcReadBuffer)) ? MakeANSI(lcReadBuffer) ENDIF ENDDO * ADD GetQueuedCompletionStatus() ENDIF IF lncounter2 = 100 EXIT ENDIF ENDDO ENDIF ENDIF CloseHandle( lh_Device ) ELSE ShowError( GetLastError(), ln_Index, 'CreateFile()' ) ENDIF ENDFOR ENDIF && Only try if RW420 found IF lifoundit ln_Index = ln_Index + 1 LOOP EXIT ENDIF ELSE llOnce = .T. && SetupDiEnumDeviceInterfaces worked at least once *--Retrieve detailed information about a specified device interface *--1. Get the required buffer size and Call SetupDiGetDeviceInterfaceDetail *-- with a NULL DeviceInterfaceDetailData pointer, *-- a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize parameter. *-- In response to such a call, this function fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, *-- and the RequiredSize parameter receives the required buffer size. *--2. Allocate an appropriately sized buffer and call the function again to get the interface details. *--1. First Call to get the required buffer size (ln_ReqSize) 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) ) *--2. Second Call with buffer sized 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 *!* IF "0a5f&pid_003e" $ LOWER(lc_DeviceName) *!* =MESSAGEBOX('This is RW420 Printer.') *!* ENDIF ?[Device Name: ],lc_DeviceName && Device Name from buffer returned from SetupDiGetDeviceInterfaceDetail() IF USED('TESTUSB') select testusb APPEND BLANK REPLACE cvalue WITH lc_DeviceName ENDIF =getvaluesfromdevice(lc_DeviceName) ?usbinfo(lc_TName) *--Create a file, file stream, directory, physical disk, volume, console buffer, tape drive *--communications resource, mailslot, or named pipe. CreateFile returns a handle to access *--the object. *!* lh_Device = CreateFile(lc_DeviceName, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, ; *!* 0, OPEN_ALWAYS, ; *!* FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) *lh_Device = CreateFile( lc_DeviceName, 0x80000000, 0x1, 0, 3, 0x20000000, 0 ) lh_Device = CreateFile(lc_DeviceName, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) IF (lh_Device != INVALID_HANDLE_VALUE) && Can use DeviceIoControl From Lh_Device also lw_Buffer = SPACE( MAX_PATH ) *--Is it a HID? Get Attributes - Deal with this later IF (HidD_GetAttributes( lh_Device, @lw_Buffer, MAX_PATH ) == 1) lc_Buffer = STRTRAN(lw_buffer,CHR(0),'') ? 'Information: ' + lc_Buffer ELSE ? [No HID Information] ENDIF *--Is it a HID? Get Product Name - Deal with this later 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 IF lnRW420 .and. lnRW420ID > 0 *--Will DeviceIoControl Work? lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13) lnWritten = 0 IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure lnRW420 = .F. lnRW420ID = 0 lcReadBuffer = REPLICATE(" ",MAX_PATH) lnBytesReturned = 0 *!* IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, 0) <> 0 *!* lncounter = 0 *!* DO WHILE lncounter < 50 *!* lncounter = lncounter + 1 *!* DOEVENTS *!* IF !EMPTY(MakeANSI(lcReadBuffer)) *!* ? MakeANSI(lcReadBuffer) *!* ENDIF *!* ENDDO *!* * ADD GetQueuedCompletionStatus() *!* ENDIF lnCounter2 = 0 DO WHILE lnBytesReturned == 0 lncounter2 = lncounter2 + 1 IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, null) <> 0 lncounter = 0 DO WHILE lncounter < 50 lncounter = lncounter + 1 DOEVENTS IF !EMPTY(MakeANSI(lcReadBuffer)) ? lcReadBuffer ? MakeANSI(lcReadBuffer) ENDIF ENDDO * ADD GetQueuedCompletionStatus() ENDIF IF lncounter2 = 100 EXIT ENDIF ENDDO ENDIF 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 !!' DO CASE CASE tn_Error = ERROR_GEN_FAILURE ? [The Device is not responding.] CASE tn_Error = ERROR_WRITE_FAULT ? [Cannot write to the device] CASE tn_Error = ERROR_READ_FAULT ? [Cannot read from device] CASE tn_Error = ERROR_OUT_OF_PAPER ? [Printer is out of paper] CASE tn_Error = ERROR_NOT_SUPPORTED ? [Request is not supported by this device] OTHERWISE ? [Error code:]+ALLTRIM(STR(tn_Error)) ENDCASE IF (VARTYPE( tn_Index ) == 'N') ? 'Member index:', ALLTRIM(STR(tn_Index)) ENDIF ENDPROC ********************************************************************************* PROCEDURE MakeANSI( tw_String ) ********************************************************************************* LOCAL lc_String, ln_Pos RETURN STRTRAN(tw_String,CHR(0),'') 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 && courtesy Carlos Alotti ********************************************************************************* 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 ********************************************************************************* FUNCTION getvaluesfromdevice (tc_DeviceName) ********************************************************************************* IF VARTYPE(tc_DeviceName) <> "C" RETURN '' ENDIF IF ! [0a5f&pid_003e] $ LOWER(tc_DeviceName) * RETURN ENDIF lh_Device = CreateFile(tc_devicename, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) *!* DECLARE INTEGER DeviceIoControl IN kernel32 ; *!* INTEGER hDevice,; *!* INTEGER dwIoControlCode,; *!* STRING @ lpInBuffer,; *!* INTEGER nInBufferSize,; *!* STRING @ lpOutBuffer,; *!* INTEGER nOutBufferSize,; *!* INTEGER lpBytesReturned,; *!* STRING @ lpOverlapped *!* *!* hDevice *!* [in] Handle to the device on which the operation is to be performed. *!* dwIoControlCode *!* [in] Control code for the operation. *!* lpInBuffer *!* [in] Pointer to the input buffer that contains the data required to perform the operation. *!* nInBufferSize *!* [in] Size of the input buffer, in bytes. *!* lpOutBuffer *!* [out] Pointer to the output buffer that is to receive the data returned by the operation. *!* nOutBufferSize *!* [in] Size of the output buffer, in bytes. *!* lpBytesReturned *!* [out] Pointer to a variable that receives the size of the data stored in the output buffer, in bytes. *!* lpOverlapped *!* [in] Pointer to an OVERLAPPED structure. *^^tch IF lh_Device !=INVALID_HANDLE_VALUE *!* #define FILE_DEVICE_UNKNOWN 0x00000022 *!* #define METHOD_BUFFERED 0 *!* #define FILE_ANY_ACCESS 0 *!* #DEFINE GET_SERIAL_NUMBER 1575952 *!* #DEFINE VENDOR_GET 222964 *!* #DEFINE VENDOR_SET 222960 m.sci = REPLICATE(CHR(0),1024) m.sco = REPLICATE(CHR(0),1024) m.ret_buffersize = 0 m.otv = DeviceIoControl( lh_Device,; GET_SERIAL_NUMBER,@m.sci,LEN(sci),@m.sco,LEN(sco),; @m.ret_buffersize,0) ? [DeviceIoControl Response: ],m.otv IF !EMPTY(m.otv) set STEP on ENDIF *--Send the command lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13) *m.sci = REPLICATE(CHR(0),1024) m.sci = lcSendValue m.sco = REPLICATE(CHR(0),1024) m.ret_buffersize = 0 m.otv = DeviceIoControl( lh_Device,; VENDOR_SET,@m.sci,LEN(sci),@m.sco,LEN(sco),; @m.ret_buffersize,0) ? [DeviceIoControl Response: ],m.otv IF !EMPTY(m.otv) set STEP on ENDIF *--Receive the data m.sci = REPLICATE(CHR(0),1024) m.sco = REPLICATE(CHR(0),1024) m.ret_buffersize = 0 m.otv = DeviceIoControl( lh_Device,; VENDOR_GET,@m.sci,LEN(sci),@m.sco,LEN(sco),; @m.ret_buffersize,0) ? [DeviceIoControl Response: ],m.otv IF !EMPTY(m.otv) set STEP on ENDIF ENDIF IF (lh_Device != INVALID_HANDLE_VALUE) && Can use DeviceIoControl From Lh_Device also lw_Buffer = SPACE( MAX_PATH ) *--Is it a HID? Get Attributes - Deal with this later lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13) lnWritten = 0 IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure lcReadBuffer = REPLICATE(" ",MAX_PATH) lnBytesReturned = 0 lnloopit = 0 CloseHandle( lh_Device ) lh_Device = CreateFile(tc_devicename, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) IF (lh_Device != INVALID_HANDLE_VALUE) && Can use DeviceIoControl From Lh_Device also DO WHILE .T. *--Send and Receive the data m.sci = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13) m.sco = REPLICATE(CHR(0),1024) m.ret_buffersize = 0 m.otv = DeviceIoControl( lh_Device,; VENDOR_GET,@m.sci,LEN(sci),@m.sco,LEN(sco),; @m.ret_buffersize,0) ? [DeviceIoControl Response: ],m.otv IF !EMPTY(m.otv) set STEP on ENDIF =ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, null) EXIT ENDDO CloseHandle( lh_Device ) ENDIF IF !EMPTY(lcReadBuffer) .or. !EMPTY(MakeANSI(lcReadBuffer)) ? [Read Buffer: ], lcReadBuffer IF !EMPTY(MakeANSI(lcReadBuffer)) ? MakeANSI(lcReadBuffer) ENDIF ELSE ? [No ReadFile] ENDIF ELSE ? [No WriteFile] ENDIF * CloseHandle( lh_Device ) ELSE ShowError( GetLastError(), 0, 'CreateFile()' ) ENDIF RETURN ********************************************************************************* FUNCTION GetLongInt(Lo, Hi) ********************************************************************************* #DEFINE MAX_DWORD 0x100000000 IF VARTYPE(m.Lo)="C" Lo = buf2dword(m.Lo) ENDIF IF VARTYPE(m.Hi) = "C" Hi = buf2dword(m.Hi) ENDIF RETURN m.Hi * MAX_DWORD + m.Lo ********************************************************************************* FUNCTION buf2dword(lcBuffer) ********************************************************************************* RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; BitLShift(Asc(SUBSTR(lcBuffer, 2,1)), 8) +; BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +; BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24) ************************************************* ************************************************************************************** * 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); FUNCTION usbinfo (tcDevicetoInfo) IF VARTYPE(tcDevicetoInfo) <> "C" return '' ENDIF DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject DECLARE INTEGER CreateFile IN kernel32 STRING lpFileName, INTEGER dwDesiredAccess, INTEGER dwShareMode, ; INTEGER lpSecurityAttributes, INTEGER dwCreationDisposition, INTEGER dwFlagsAndAttributes, ; INTEGER hTemplateFile DECLARE INTEGER DeviceIoControl IN kernel32 INTEGER hDevice, INTEGER dwIoControlCode, STRING @lpInBuffer, ; LONG nInBufferSize, STRING @lpOutBuffer, LONG nOutBufferSize, INTEGER @lpBytesReturned, ; INTEGER lpOverlapped DECLARE INTEGER GetLogicalDriveStrings IN Win32API INTEGER buflen, STRING @buf DECLARE INTEGER GetDriveType IN kernel32 ; STRING nDrive DECLARE INTEGER GetVolumeInformation IN Win32API ; STRING lpRootPathName, STRING @lpVolumeNameBuffer, ; INTEGER nVolumeNameSize, LONG @lpVolumeSerialNumber, ; INTEGER @lpMaximumComponentLength, INTEGER @lpFileSystemFlags, ; STRING @lpFileSystemNameBuffer, INTEGER nFileSystemNameSize m.vnb=REPLICATE(CHR(0),64) m.vnbs=64 m.vsn=0 m.mcl=0 m.fsf=0 m.fsnb=REPLICATE(CHR(0),10) m.fsnbs=10 * handle = CreateFile(tcDevicetoInfo, 0xC0000000, 3,0, 3, 0, 0) handle = CreateFile(tcDevicetoInfo, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) m.sn="" m.model="" m.rev="" IF handle <> -1 m.sci="" m.sci=m.sci+CHR(0)+CHR(2)+CHR(0)+CHR(0) m.sci=m.sci+CHR(0) m.sci=m.sci+CHR(1) m.sci=m.sci+CHR(1) m.sci=m.sci+CHR(0) m.sci=m.sci+CHR(0) m.sci=m.sci+CHR(0xA0) m.sci=m.sci+CHR(0xEC) m.sci=m.sci+CHR(0) m.sci=m.sci+CHR(0) m.sci=m.sci+REPL(CHR(0),499) m.sco=REPLICATE(CHR(0),2048) m.ret_buffersize=0 m.otv=DeviceIoControl(handle, 0x7C088, @m.sci, LEN(sci), @m.sco, LEN(sco),@m.ret_buffersize, 0) CloseHandle(handle) IF m.otv<>0 m.sn=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,37,20))),CHR(0),"") m.rev=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,63,8))),CHR(0),"") m.model=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,71,40))),CHR(0),"") ENDIF ENDIF IF EMPTY(m.sn) m.sn="" * handle = CreateFile(tcDevicetoInfo, 0xC0000000, 3,0, 3, 0, 0) handle = CreateFile(tcDevicetoInfo, ; GENERIC_READ + GENERIC_WRITE ,; FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) IF handle <> -1 m.sn="" m.model="" m.rev="" m.sci=REPLICATE(CHR(0),1024) m.sco=REPLICATE(CHR(0),1024) m.ret_buffersize=0 m.otv=DeviceIoControl(handle, 0x2D1400, @m.sci, LEN(sci), @m.sco,LEN(sco), @m.ret_buffersize, 0) CloseHandle(handle) IF m.otv<>0 m.pos0=ASC(SUBSTR(m.sco,13,1)) m.pos1=ASC(SUBSTR(m.sco,17,1)) IF m.pos0>0 m.pos1=m.pos0 ENDIF m.pos2=ASC(SUBSTR(m.sco,21,1)) m.pos3=ASC(SUBSTR(m.sco,25,1)) m.model=SUBSTR(m.sco,m.pos1+1,m.pos2-m.pos1) m.pos4=AT(CHR(0),m.model) IF m.pos4>0 m.model=ALLT(CHRTRAN(m.model,CHR(0),"")) ENDIF IF m.pos3>m.pos2 m.rev=SUBSTR(m.sco,m.pos2+1,m.pos3-m.pos2) ELSE m.rev=SUBSTR(m.sco,m.pos2+1) ENDIF m.pos4=AT(CHR(0),m.rev) IF m.pos4>0 m.rev=ALLT(LEFT(m.rev,m.pos4-1)) ENDIF IF m.pos3>0 m.pos3=m.pos3+1 m.sco1=SUBSTR(m.sco, m.pos3,40) m.sco1=ALLT(m.sco1) m.sn="" m.pos3=1 FOR m.j=1 TO 20 m.ch1=CHR(EVAL("0x"+ALLT(SUBSTR(m.sco1,m.pos3,2)))) m.pos3=m.pos3+2 m.ch2=CHR(EVAL("0x"+ALLT(SUBSTR(m.sco1,m.pos3,2)))) m.pos3=m.pos3+2 m.sn=m.sn+m.ch2+m.ch1 ENDFOR m.sn=ALLT(CHRTRAN(m.sn,CHR(0),"")) ELSE m.sn="" ENDIF ENDIF ENDIF ENDIF m.str1='' lcinfo = m.str1 lcinfo = lcinfo + CHR(13) IF TYPE('m.vsn') = "N" m.vsn = ALLTRIM(STR(m.vsn)) ENDIF lcinfo = lcinfo + "VolSN: " + STRTRAN(m.vsn,CHR(0),'') + CHR(13) lcinfo = lcinfo + "Type: "+ STRTRAN(m.fsnb,CHR(0),"") + CHR(13) lcinfo = lcinfo + "Model: " + STRTRAN(m.model,CHR(0),'') + CHR(13) lcinfo = lcinfo + "Revision: " + STRTRAN(m.rev,CHR(0),'') + CHR(13) lcinfo = lcinfo + "Serial #: " + STRTRAN(m.sn,CHR(0),'') ?STRTRAN(lcinfo,CHR(13),CHR(10)) IF !EMPTY(m.sn) .or. !EMPTY(m.rev) .or. !EMPTY(m.model) .or. !EMPTY(m.vsn) .or. !EMPTY(m.fsnb) MESSAGEBOX(lcinfo) ENDIF RETURN FUNCTION conv21 LPARAMETERS m.str IF LEN(m.str)%2=1 m.str=m.str+" " ENDIF LOCAL m.i, m.str2 m.str2="" FOR m.i=1 TO LEN(m.str) m.str2=m.str2+SUBSTR(m.str,m.i+IIF(m.i%2=0,-1,1),1) NEXT RETURN m.str2>>OK