oform = CREATEOBJECT('DeviceInfoForm') oform.show() read events return DEFINE CLASS deviceinfoForm AS form Height = 554 Width = 988 DoCreate = .T. ShowTips = .T. AutoCenter = .T. Caption = "System Device Information" WindowType = 0 WindowState = 0 *-- The error message. Same as MESSAGE().Same as AERROR element 2. message = "Select a SubCategory" Name = "DEVICEINFO" DIMENSION devicearray[1,8] ADD OBJECT oletreeview AS olecontrol WITH ; Top = 33, ; Left = 2, ; Height = 519, ; Width = 427, ; TabIndex = 4, ; Name = "oleTreeView" ADD OBJECT owb AS olecontrol WITH ; Top = 33, ; Left = 432, ; Height = 519, ; Width = 552, ; Name = "oWB" ADD OBJECT cmdclose AS commandbutton WITH ; Top = 0, ; Left = 852, ; Height = 32, ; Width = 108, ; Caption = "Close", ; TabStop = .F., ; Name = "cmdClose" ADD OBJECT cmdsystem AS commandbutton WITH ; Top = 0, ; Left = 12, ; Height = 32, ; Width = 144, ; Caption = "Get All System Devices", ; TabStop = .F., ; Name = "cmdSystem" ADD OBJECT cmdpresent AS commandbutton WITH ; Top = 0, ; Left = 168, ; Height = 32, ; Width = 144, ; Caption = "Get All Devices Present", ; TabStop = .F., ; Name = "cmdPresent" PROCEDURE filltree LPARAMETERS cHeading IF TYPE('cHeading') <> "C" .or. EMPTY(cHeading) cHeading = 'Results' ENDIF IF TYPE('ALEN(thisform.devicearray,1)') <> "N" .OR. ALEN(thisform.devicearray,1) = 0 RETURN ENDIF #define tvwFirst 0 && The Node is placed before all other nodes at the same level of the node named in relative. #define tvwLast 1 && The Node is placed after all other nodes at the same level of the node named in relative. Any Node added subsequently may be placed after one added as Last. #define tvwNext 2 && (Default) The Node is placed after the node named in relative. #define tvwPrevious 3 && The Node is placed before the node named in relative. #define tvwChild 4 && The Node becomes a child node of the node named in relative.#DEFINE tvwFirst 0 #DEFINE cnLOG_PIXELS_X 88 #DEFINE cnLOG_PIXELS_Y 90 #DEFINE cnTWIPS_PER_INCH 1440 PRIVATE onode, tnode, xnode, treetopkey, parentid, childid THIS.oletreeview.nodes.clear() treetopkey = '' parentid = '' childid = '' WITH THIS.oletreeview.nodes IF treetopkey = '' treetopkey = '0_0' nodeid = treetopkey tnode=.ADD(,tvwFirst,treetopkey,ALLTRIM(cHeading)) xnode = tnode ENDIF IF TYPE('tnode')="O" tnode.expanded = .T. ELSE RETURN ENDIF FOR icount = 1 TO ALEN(thisform.devicearray,1) IF TYPE('thisform.devicearray(icount,1)') <> "N" LOOP ENDIF *--Device ID is parent node but we will display the device class instead parentid = ALLTRIM(STR(icount))+":"+ALLTRIM(STR(thisform.devicearray(icount,1))) IF TYPE('thisform.devicearray(icount,2)') = "N" tnode=.ADD(,tvwFirst,parentid,ALLTRIM(STR(thisform.devicearray(icount,2)))) ELSE tnode=.ADD(,tvwFirst,parentid,ALLTRIM(thisform.devicearray(icount,2))) ENDIF *--Item Specifics 2 - 8 Child Node of Device ID IF TYPE('thisform.devicearray(icount,1)')= "C" childid = parentid+":"+"1" && 2nd column tnode=.ADD(parentid,tvwChild,childid,'ID: '+ALLTRIM(thisform.devicearray(icount,1))) ELSE childid = parentid+":"+"1" && 2nd column tnode=.ADD(parentid,tvwChild,childid,'ID: '+ALLTRIM(STR(thisform.devicearray(icount,1)))) ENDIF childid = parentid+":"+"3" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,3))) childid = parentid+":"+"4" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,4))) childid = parentid+":"+"5" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,5))) childid = parentid+":"+"6" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,6))) childid = parentid+":"+"7" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,7))) childid = parentid+":"+"8" && 2nd column tnode=.ADD(parentid,tvwChild,childid,ALLTRIM(thisform.devicearray(icount,8))) ENDFOR ENDWITH *--Expand the very top parent only IF TYPE('xnode')="O" .and. TYPE('treetopkey')="C" .and. !EMPTY(treetopkey) THIS.oletreeview.nodes(treetopkey).Selected=.t. THIS.oletreeview.nodeclick(xnode) ENDIF THISFORM.REFRESH() THISFORM.RESIZE() THISFORM.REFRESH() WAIT WINDOW "Finished!" NOWAIT RETURN .T. ENDPROC PROCEDURE stuffdevarray *References: UT Message #1159601 Courtesy Christian Ehlscheid *Message #1157717 Courtesy Carlos Alloatti *http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q264203 *http://msdn.microsoft.com/library/default.asp?url=/library/en- *us/devio/base/setupdienumdeviceinterfaces.asp WAIT WINDOW "Gathering Device Information..." NOWAIT TIMEOUT 30 cguid = '' && ignored for all values *!* DIGCF_ALLCLASSES *!* Return a list of installed devices for all device setup classes or all device interface classes. *!* DIGCF_DEVICEINTERFACE *!* Return devices that support device interfaces for the specified device interface classes. *!* DIGCF_DEFAULT *!* Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes. *!* DIGCF_PRESENT *!* Return only devices that are currently present in a system. *!* DIGCF_PROFILE *!* Return only devices that are a part of the current hardware profile. #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_DEFAULT 0x00000001 // only valid with DIGCF_DEVICEINTERFACE *!* #define DIGCF_PRESENT 0x00000002 *!* #define DIGCF_ALLCLASSES 0x00000004 *!* #define DIGCF_PROFILE 0x00000008 *!* #define DIGCF_DEVICEINTERFACE 0x00000010 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. DO WHILE .T. * lnpointer = setupdigetclassdevs(@cGuid, NULL, 0, DIGCF_INTERFACEDEVICE) 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 * DO WHILE .T. && setup a SP_DEVICE_INTERFACE_DATA structure, && BINTOC sets dwSize member to 28, + SPACE(24) for the && rest of the structure *lcinterfacedata = BINTOC(28,'RS') + SPACE(24) *?deviceinfoset *?ninfo *?cguid *?lcInterfacedata m.lcDeviceInfoData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lnRetVal = SetupDiEnumDeviceInfo( ; m.lnDeviceInfoSet, ; m.lnx, ; @m.lcDeviceInfoData) *?m.lnRetVal IF m.lnRetVal = 0 * IF !setupdienumdeviceinterfaces(deviceinfoset, @ninfo , @cGuid, i, @lcinterfacedata) 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 = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_CLASS) *?[Property:], [CLASS: ], m.lcDeviceProperty devicearray(m.iloop,2) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_DEVICEDESC) *?[Property:], [DEVICEDESC: ], m.lcDeviceProperty devicearray(m.iloop,3) = m.lcDeviceProperty IF TYPE('m.lcDeviceProperty') = "C" WAIT WINDOW ALLTRIM(STR(iloop))+' - '+m.lcDeviceProperty+'...' NOWAIT ENDIF m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME) *?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty devicearray(m.iloop,4) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME) *?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty devicearray(m.iloop,5) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_HARDWAREID) *?[Property:], [HARDWAREID: ], m.lcDeviceProperty devicearray(m.iloop,6) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_MFG) *?[Property:], [MFG: ], m.lcDeviceProperty devicearray(m.iloop,7) = m.lcDeviceProperty m.lcDeviceProperty = thisform.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 EXIT ENDIF ENDDO ELSE *? [SetupDiGetClassDevs FAILED] ENDIF EXIT ENDDO *? 'Found '+ALLTRIM(STR(m.lnx))+' devices.' IF TYPE('ALEN(devicearray,1)') = "N" .and. ALEN(devicearray,1) > 0 *!* FOR icheck = 1 TO ALEN(devicearray,1) *!* IF TYPE('devicearray(Icheck,1)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,1)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column1' *!* ENDIF *!* IF TYPE('devicearray(Icheck,2)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,2)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 2' *!* ENDIF *!* IF TYPE('devicearray(Icheck,3)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,3)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 3' *!* ENDIF *!* IF TYPE('devicearray(Icheck,4)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,4)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 4' *!* ENDIF *!* IF TYPE('devicearray(Icheck,5)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,5)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 5' *!* ENDIF *!* IF TYPE('devicearray(Icheck,6)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,6)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 6' *!* ENDIF *!* IF TYPE('devicearray(Icheck,7)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,7)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 7' *!* ENDIF *!* IF TYPE('devicearray(Icheck,8)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,8)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 8' *!* ENDIF *!* ENDFOR DIMENSION thisform.devicearray(ALEN(devicearray,1),8) =ACOPY(devicearray,thisform.devicearray) ELSE DIMENSION thisform.devicearray(1,8) thisform.devicearray(1,1) = 'No Information Available' thisform.devicearray(1,2) = 'No Information Available' thisform.devicearray(1,3) = 'No Information Available' thisform.devicearray(1,4) = 'No Information Available' thisform.devicearray(1,5) = 'No Information Available' thisform.devicearray(1,6) = 'No Information Available' thisform.devicearray(1,7) = 'No Information Available' thisform.devicearray(1,8) = 'No Information Available' 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 CLEAR DLLS RETURN ENDPROC PROCEDURE getregistryproperty ********************************************************************************* *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 = [No Value Returned] Else m.lcPropertyBuffer = Left(m.lcPropertyBuffer, At(Chr(0), m.lcPropertyBuffer) - 1) Endif Return m.lcPropertyBuffer ENDPROC PROCEDURE getallpresent WAIT WINDOW "Gathering Device Information..." NOWAIT TIMEOUT 30 cguid = [{36FC9E60-C465-11CF-8056-444553540000}] && All USB Device Interfaces *!* DIGCF_ALLCLASSES *!* Return a list of installed devices for all device setup classes or all device interface classes. *!* DIGCF_DEVICEINTERFACE *!* Return devices that support device interfaces for the specified device interface classes. *!* DIGCF_DEFAULT *!* Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes. *!* DIGCF_PRESENT *!* Return only devices that are currently present in a system. *!* DIGCF_PROFILE *!* Return only devices that are a part of the current hardware profile. #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_DEFAULT 0x00000001 // only valid with DIGCF_DEVICEINTERFACE *!* #define DIGCF_PRESENT 0x00000002 *!* #define DIGCF_ALLCLASSES 0x00000004 *!* #define DIGCF_PROFILE 0x00000008 *!* #define DIGCF_DEVICEINTERFACE 0x00000010 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. DO WHILE .T. lnpointer = setupdigetclassdevs(@cGuid, NULL, 0, DIGCF_DEVICEINTERFACE) 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 * DO WHILE .T. && setup a SP_DEVICE_INTERFACE_DATA structure, && BINTOC sets dwSize member to 28, + SPACE(24) for the && rest of the structure *lcinterfacedata = BINTOC(28,'RS') + SPACE(24) *?deviceinfoset *?ninfo *?cguid *?lcInterfacedata m.lcDeviceInfoData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lnRetVal = SetupDiEnumDeviceInfo( ; m.lnDeviceInfoSet, ; m.lnx, ; @m.lcDeviceInfoData) *?m.lnRetVal IF m.lnRetVal = 0 * IF !setupdienumdeviceinterfaces(deviceinfoset, @ninfo , @cGuid, i, @lcinterfacedata) 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 = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_CLASS) *?[Property:], [CLASS: ], m.lcDeviceProperty devicearray(m.iloop,2) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_DEVICEDESC) *?[Property:], [DEVICEDESC: ], m.lcDeviceProperty devicearray(m.iloop,3) = m.lcDeviceProperty IF TYPE('m.lcDeviceProperty') = "C" WAIT WINDOW ALLTRIM(STR(iloop))+' - '+m.lcDeviceProperty+'...' NOWAIT ENDIF m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME) *?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty devicearray(m.iloop,4) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME) *?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty devicearray(m.iloop,5) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_HARDWAREID) *?[Property:], [HARDWAREID: ], m.lcDeviceProperty devicearray(m.iloop,6) = m.lcDeviceProperty m.lcDeviceProperty = thisform.getregistryproperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_MFG) *?[Property:], [MFG: ], m.lcDeviceProperty devicearray(m.iloop,7) = m.lcDeviceProperty m.lcDeviceProperty = thisform.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 EXIT ENDIF ENDDO ELSE *? [SetupDiGetClassDevs FAILED] ENDIF EXIT ENDDO *? 'Found '+ALLTRIM(STR(m.lnx))+' devices.' IF TYPE('ALEN(devicearray,1)') = "N" .and. ALEN(devicearray,1) > 0 *!* FOR icheck = 1 TO ALEN(devicearray,1) *!* IF TYPE('devicearray(Icheck,1)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,1)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column1' *!* ENDIF *!* IF TYPE('devicearray(Icheck,2)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,2)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 2' *!* ENDIF *!* IF TYPE('devicearray(Icheck,3)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,3)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 3' *!* ENDIF *!* IF TYPE('devicearray(Icheck,4)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,4)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 4' *!* ENDIF *!* IF TYPE('devicearray(Icheck,5)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,5)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 5' *!* ENDIF *!* IF TYPE('devicearray(Icheck,6)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,6)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 6' *!* ENDIF *!* IF TYPE('devicearray(Icheck,7)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,7)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 7' *!* ENDIF *!* IF TYPE('devicearray(Icheck,8)') = "C" .and. 'RW420' $ UPPER(devicearray(icheck,8)) *!* *? 'Found RW420 in element: '+ALLTRIM(STR(icheck))+' Column 8' *!* ENDIF *!* ENDFOR DIMENSION thisform.devicearray(ALEN(devicearray,1),8) =ACOPY(devicearray,thisform.devicearray) ELSE DIMENSION thisform.devicearray(1,8) thisform.devicearray(1,1) = 'No Information Available' thisform.devicearray(1,2) = 'No Information Available' thisform.devicearray(1,3) = 'No Information Available' thisform.devicearray(1,4) = 'No Information Available' thisform.devicearray(1,5) = 'No Information Available' thisform.devicearray(1,6) = 'No Information Available' thisform.devicearray(1,7) = 'No Information Available' thisform.devicearray(1,8) = 'No Information Available' 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 CLEAR DLLS RETURN ENDPROC PROCEDURE Init SET SAFETY OFF SET TALK OFF _VFP.AUTOYIELD = .T. sysalias = ALIAS() IF TYPE('ddir')="U" PUBLIC ddir ddir = SYS(2003) IF RIGHT(ddir,1) <> "\" ddir = ddir + "\" ENDIF ENDIF *!* IF TYPE('oSysInfo') <> "O" .OR. ISNULL(oSysInfo) *!* IF !USED('SYSINFO') *!* SELE 0 *!* USE (ddir+"SYSINFO") *!* IF !USED('SYSINFO') *!* =MESSAGEBOX('Unable to access system information table.') *!* IF !EMPTY(sysalias) .AND. USED(sysalias) *!* SELECT (sysalias) *!* ENDIF *!* RETURN .F. *!* ENDIF *!* ENDIF *!* ELSE *!* IF !USED('SYSINFO') *!* oSysInfo.setup() *!* ENDIF *!* oSysInfo.verify() *!* *--Popuser is done only if forced refresh is set here or if blank *!* *--Popcommon is always done here when loading this form *!* oSysInfo.popcommon() *!* oSysInfo.popuser() *!* ENDIF *!* SELE sysinfo *!* SET ORDER TO TAG callfields *!* GO TOP *!* IF EOF('SYSINFO') *!* =MESSAGEBOX('There are no records to view.') *!* IF !EMPTY(sysalias) .AND. USED(sysalias) *!* SELECT (sysalias) *!* ENDIF *!* RETURN .F. *!* ENDIF *!* SELE SysInfo DODEFAULT() IF TYPE("THIS.oleTreeView") # "O" OR ISNULL(THIS.oletreeview) RETURN .F. ENDIF WITH THIS.oletreeview .linestyle =1 .labeledit =1 .indentation = 5 .PathSeparator = '\' .SCROLL = .T. .OLEDRAGMODE = 0 .OLEDROPMODE = 0 ENDWITH WITH THISFORM.oWB .Navigate("about:blank") lnStartSeconds = SECONDS() DO WHILE .ReadyState <> 4 ; AND (SECONDS()-lnStartSeconds <= 1 ) DOEVENTS ENDDO .DOCUMENT.OPEN() .Document.Write('') .DOCUMENT.CLOSE() ENDWITH this.refresh() thisform.stuffdevarray() thisform.filltree('All System Devices') WAIT CLEAR ENDPROC PROCEDURE QueryUnload IF TYPE('oSysInfo') <> "O" .OR. ISNULL(oSysInfo) IF USED('SYSINFO') USE IN SYSINFO ENDIF ELSE oSysInfo.cleanup() ENDIF RETURN .T. ENDPROC PROCEDURE Unload CLEAR EVENTS DODEFAULT() ENDPROC PROCEDURE oletreeview.NodeClick *** ActiveX Control Event *** LPARAMETERS NODE NODE.ensurevisible IF '0_0' $ NODE.KEY .AND. ALEN(THISFORM.devicearray,1) > 0 WITH THISFORM.oWB .NAVIGATE("about:blank") lnStartSeconds = SECONDS() DO WHILE .ReadyState <> 4 ; AND (SECONDS()-lnStartSeconds <= 1 ) DOEVENTS ENDDO .DOCUMENT.OPEN() .DOCUMENT.WRITE('Click on any item for more information'+chr(13)+chr(13)) .DOCUMENT.CLOSE() ENDWITH ELSE IF INT(VAL(LEFT(NODE.KEY,AT(":",NODE.KEY)-1))) > 0 lnpos = INT(VAL(LEFT(NODE.KEY,AT(":",NODE.KEY)-1))) WITH THISFORM.oWB .NAVIGATE("about:blank") lnStartSeconds = SECONDS() DO WHILE .ReadyState <> 4 ; AND (SECONDS()-lnStartSeconds <= 1 ) DOEVENTS ENDDO IF lnpos > 0 .DOCUMENT.OPEN() myvalue = 'CLASS: '+THISFORM.devicearray(lnpos,2)+chr(13)+chr(13) myvalue = myvalue + 'DEVICE DESCRIPTION: '+THISFORM.devicearray(lnpos,3)+chr(13)+chr(13) myvalue = myvalue + 'ENUMERATOR NAME: '+THISFORM.devicearray(lnpos,4)+chr(13)+chr(13) myvalue = myvalue + 'FRIENDLY NAME: '+THISFORM.devicearray(lnpos,5)+chr(13)+chr(13) myvalue = myvalue + 'HARDWARE ID: '+THISFORM.devicearray(lnpos,6)+chr(13)+chr(13) myvalue = myvalue + 'MFG: '+THISFORM.devicearray(lnpos,7)+chr(13)+chr(13) myvalue = myvalue + 'PHYSICAL DEVICE OBJECT NAME: '+THISFORM.devicearray(lnpos,8)+chr(13)+chr(13) .DOCUMENT.WRITE(myvalue) .DOCUMENT.CLOSE() ELSE .DOCUMENT.OPEN() .DOCUMENT.WRITE('No Additional Information Available'+chr(13)+chr(13)) .DOCUMENT.CLOSE() ENDIF ENDWITH ELSE WITH THISFORM.oWB .NAVIGATE("about:blank") lnStartSeconds = SECONDS() DO WHILE .ReadyState <> 4 ; AND (SECONDS()-lnStartSeconds <= 1 ) DOEVENTS ENDDO .DOCUMENT.OPEN() .DOCUMENT.WRITE('No Additional Information Available'+chr(13)+chr(13)) .DOCUMENT.CLOSE() ENDWITH ENDIF ENDIF ENDPROC PROCEDURE oletreeview.NodeCheck *** ActiveX Control Event *** LPARAMETERS node ENDPROC PROCEDURE owb.Refresh *** ActiveX Control Method *** NODEFAULT ENDPROC PROCEDURE cmdclose.Click IF THISFORM.queryunload() thisform.release() ENDIF ENDPROC PROCEDURE cmdsystem.Click thisform.stuffdevarray() thisform.filltree('All System Devices') WAIT CLEAR ENDPROC PROCEDURE cmdpresent.Click wait WINDOW "Clearing Results..." NOWAIT TIMEOUT 30 THISFORM.oletreeview.nodes.clear() doevents thisform.refresh() thisform.getallpresent() thisform.filltree('All Devices Present') WAIT CLEAR ENDPROC ENDDEFINETry this Program (works all the way until we get to SetupDiEnumDeviceInterfaces()
*References: UT Message #1159601 Courtesy Christian Ehlscheid *Message #1157717 Courtesy Carlos Alloatti *http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q264203 *http://msdn.microsoft.com/library/default.asp?url=/library/en- *us/devio/base/setupdienumdeviceinterfaces.asp *!* typedef struct _SP_DEVINFO_DATA { *!* DWORD cbSize; 4 *!* GUID ClassGuid; 16 *!* DWORD DevInst; 4 *!* ULONG_PTR Reserved; 4 *!* } SP_DEVINFO_DATA 28 *!* Private Type Guid *!* Data1 As Long 4 *!* Data2 As Integer 2 *!* Data3 As Integer 2 *!* Data4(0 To 7) As Byte 8 *!* End Type 16 ********************************************************************************* *!* Defines ********************************************************************************* #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 *!* 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) ********************************************************************************* *!* Declarations, in order of use ********************************************************************************* Declare Integer SetupDiGetClassDevs In setupapi; String @ClassGuid,; Integer Enumerator,; Integer hwndParent,; Integer _Flags 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 SetupDiEnumDeviceInterfaces IN setupapi; INTEGER DeviceInfoSet,; STRING @ DeviceInfoData,; STRING @ ByRefterfaceClassGuid,; INTEGER MemberIndex,; STRING @ DeviceInterfaceData Declare Integer GetLastError In win32api Declare Integer SetupDiDestroyDeviceInfoList In setupapi; Integer DeviceInfoSet ********************************************************************************* *!* Start ********************************************************************************* *!* This routine enumerates the disk devices using the Setup class interface *!* GUID GUID_DEVCLASS_DISKDRIVE. Gets the Device ID from the Registry *!* property. Clear Local ; lnDeviceInfoSet, ; lnEnumerator, ; lnhwndParent, ; lnFlags, ; lcClassGuid, ; lnRetVal, ; lcDeviceInfoData, ; lnx, ; lcDeviceProperty *!* We will first obtain a handle to a list of all disk drives available: *!* "The SetupDiGetClassDevs function retrieves a device information set *!* that contains all the devices of a specified class." m.lcClassGuid = GUID_DEVCLASS_DISKDRIVE m.lnEnumerator = 0 m.lnhwndParent = 0 m.lnFlags = DIGCF_PRESENT m.lnDeviceInfoSet = SetupDiGetClassDevs( ; @m.lcClassGuid, ; m.lnEnumerator, ; m.lnhwndParent, ; m.lnFlags) && All devices present on system *!* If the return value is -1 something went wrong If m.lnDeviceInfoSet = INVALID_HANDLE_VALUE Then ? [SetupDiGetClassDevs FAILED] Return Endif *!* Now that we have a handle to the list of disk drives, we will go thru *!* that list one device at a time: *!* "The SetupDiEnumDeviceInfo function retrieves a context structure for *!* a device information element of the specified device information set. *!* Each call returns information about one device. The function can be *!* called repeatedly to get information about several devices." *!* When SetupDiEnumDeviceInfo fails, we get out of the loop, and check why it failed *!* It will probably fail because we iterated trhu all devices m.lnx = 0 m.lnRetVal = -1 Do While m.lnRetVal <> 0 *!* Initialize empty SP_DEVINFO_DATA structure m.lcDeviceInfoData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lnRetVal = SetupDiEnumDeviceInfo( ; m.lnDeviceInfoSet, ; m.lnx, ; @m.lcDeviceInfoData) *!* If we got a handle to one disk drive, now we will retrieve some properties for it: If m.lnRetVal = 1 Then ?[Device: ], m.lnx m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_CLASS) ?[Property:], [CLASS: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_DEVICEDESC) ?[Property:], [DEVICEDESC: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME) ?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME) ?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_HARDWAREID) ?[Property:], [HARDWAREID: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_MFG) ?[Property:], [MFG: ], m.lcDeviceProperty m.lcDeviceProperty = GetRegistryProperty(m.lnDeviceInfoSet, m.lcDeviceInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME) ?[Property:], [PHYSICAL_DEVICE_OBJECT_NAME: ], m.lcDeviceProperty Endif m.lnx = m.lnx + 1 Enddo *** BEGIN Test Portion m.lcDeviceInfoData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lnx = 0 *--Try the setupdienumdeviceinterfaces() instead m.lcDeviceInterfaceData = Padr(BinToC(28, [4RS]), 4, Chr(0)) + Replicate(Chr(0), 24) m.lcDeviceInterfaceData = CHR(32)+CHR(0)+CHR(0)+CHR(0) &&dword only m.lcDeviceInterfaceData = long2str(32)+REPLICATE(CHR(0),28) m.lcDeviceInterfaceData = num2dword(32)+num2dword(0)+num2dword(0)+ ; num2dword(0)+num2dword(0) m.returnvalue = SetupDiEnumDeviceInterfaces( ; m.lnDeviceInfoSet, ; @m.lcDeviceInfoData, ; @m.lcClassGuid, ; m.lnx,; @m.lcDeviceInterfaceData) IF m.returnvalue <> 0 ? [Success with SetupDiEnumDeviceInterfaces()] ELSE ? [Failure with SetupDiEnumDeviceInterfaces()] m.errvalue = getlasterror() ?m.errvalue IF m.errvalue = error_no_more_items ELSE ENDIF ENDIF *** END Test Portion If GetLastError() = ERROR_NO_MORE_ITEMS Then ?[No more devices] Else ?[SetupDiEnumDeviceInfo FAILED] Endif *!* The SetupDiDestroyDeviceInfoList function destroys a device *!* information set and frees all associated memory. If m.lnDeviceInfoSet <> INVALID_HANDLE_VALUE Then If SetupDiDestroyDeviceInfoList(m.lnDeviceInfoSet) = 0 Then ? [SetupDiDestroyDeviceInfoList lnDeviceInfoSet FAILED] Endif Endif 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 FUNCTION long2str PARAMETERS m.longval PRIVATE i, m.retstr m.retstr = "" FOR i = 24 TO 0 STEP -8 m.retstr = CHR(INT(m.longval/(2^i))) + m.retstr m.longval = MOD(m.longval, (2^i)) ENDFOR RETURN m.retstr FUNCTION str2long PARAMETERS m.longstr PRIVATE i, m.retval m.retval = 0 FOR i = 0 TO 24 STEP 8 m.retval = m.retval + (ASC(m.longstr) * (2^i)) m.longstr = RIGHT(m.longstr, LEN(m.longstr) - 1) NEXT RETURN m.retval FUNCTION num2dword (lnValue) #DEFINE m0 256 #DEFINE m1 65536 #DEFINE m2 16777216 LOCAL b0, b1, b2, b3 b3 = Int(lnValue/m2) b2 = Int((lnValue - b3 * m2)/m1) b1 = Int((lnValue - b3*m2 - b2*m1)/m0) b0 = Mod(lnValue, m0) RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) FUNCTION num2word (lnValue) RETURN Chr(Mod(m.lnValue,256)) + Chr(Int(m.lnValue/256))