//device 硬件设备列表
import win.guid;
import win.reg;

namespace sys;

class device{
	ctor( classGuid,enumerator,flags = 2/*_DIGCF_PRESENT*/,hwndParent){
	
		if( classGuid === null ) flags = flags | 4/*_DIGCF_ALLCLASSES*/
		elseif(type.isString(classGuid)) classGuid = ..win.guid.fromString(classGuid);
		
		this.hDevInfo  =  ::Setupapi.SetupDiGetClassDevs(classGuid, enumerator,  hwndParent,  flags); 
		if(!this.hDevInfo) return;
		
		..table.gc(this,"destroy");
	};
	each = function(...){
		
		
		var idx = 0;
		var propertyType = {...}
		return function(){
			var adapterData = SP_DEVINFO_DATA();
			if(::Setupapi.SetupDiEnumDeviceInfo(this.hDevInfo,idx,adapterData)){
				
				var property = {};
				for(i=1;#propertyType;1){
					if(type.isString(propertyType[i])){
						var hkey =::Setupapi.SetupDiOpenDevRegKey(this.hDevInfo,adapterData,1/*_DICS_FLAG_GLOBAL*/, 0, 1/*_DIREG_DEV*/, 1/*_KEY_QUERY_VALUE*/) 
						if(!hkey) continue;
							
						var reg = ..win.reg(hkey);
						property[i] = reg.queryValue(propertyType[i]);
						reg.close();
						continue;
					}
					
					var ret,dataType,propertyBuffer,requiredSize = SetupDiGetDeviceRegistryProperty(this.hDevInfo,adapterData,propertyType[i],0,0,0,0);
					if(requiredSize) {
						ret,dataType,propertyBuffer,requiredSize =  SetupDiGetDeviceRegistryProperty(this.hDevInfo,adapterData,propertyType[i],0,requiredSize,requiredSize,0);

						select(dataType) { 
								case 0x1/*_REG_SZ*/,0x2/*_REG_EXPAND_SZ*/ {
									property[i] = ..string.fromUnicode(propertyBuffer);
									property[i] = ..string.trimright(property[i],'\0');
								}
								case 0x4/*_REG_DWORD*/ {
									property[i] = ..raw.convert(propertyBuffer ,{INT v }).v; 
								}
								case 0x5/*_REG_DWORD_BIG_ENDIAN*/ {
									property[i] = ..raw.swap(  ..raw.convert(propertyBuffer ,{INT v }).v );  
								}
								case 0x3/*_REG_BINARY*/ {
									property[i] = propertyBuffer;
								} 
								case 0x7/*_REG_MULTI_SZ*/ {
									var p = ..string.fromUnicode(propertyBuffer,,requiredSize/2);
									p = ..string.trimright(p,'\0');
									property[i] = ..string.split(p,'\0'); 
								}
								else {
									property[i] = propertyBuffer;
								} 
							} 
						}
				}
				
				idx ++;
				..table.push(property,adapterData)
				return idx,..table.unpackArgs( property )
			}
		}
	};
	destroy = function(){
		if(this.hDevInfo ){
			::Setupapi.SetupDiDestroyDeviceInfoList(this.hDevInfo );
			this.hDevInfo = null;
		};
	}; 
}
	
namespace device{
	
	manager = function(winform){
		..raw.loadDll("devmgr.dll").DeviceManager_Execute(winform[["hwnd"]]||winform,_HINSTANSE,"",5/*_SW_SHOW*/);
	}
	
	::Setupapi := ..raw.loadDll("Setupapi.dll");
	SetupDiGetDeviceRegistryProperty = ::Setupapi.api("SetupDiGetDeviceRegistryProperty"
	,"bool(addr deviceInfoSet,struct deviceInfoData,INT property,INT &dataType,string &propertyBuffer,INT propertyBufferSize,INT &requiredSize)" );
	
	class SP_DEVINFO_DATA {
		INT cbSize = 28;
		struct classGuid = ..win.guid();
		INT devInst;
		ADDR reserved;
	}
}

/**intellisense()
sys.device = 用于获取硬件设备列表
sys.device(.("设备类名","枚举键名",选项,父窗口句柄) = 获取设备列表，所有参数可选，\n设备类名可以设备管理器中查看,可输入 _GUID_DEVCLASS_ 前缀的常量自动转换,\n枚举键名可以是PCI,USB等等,也可以省略\n参数请参考SetupDiGetClassDevs这个API的文档
sys.device() = !stdSysDevice.
!SP_DEVINFO_DATA.devInst = 设备句柄
!SP_DEVINFO_DATA.classGuid = 设备类 GUID,\nwin.guid 对象
!stdSysDevice.each() = !SP_DEVINFO_DATA.
!stdSysDevice.each(任意个字段类型参数) = @for( index,classGuid,deviceDesc,devInfo in ??.each(\n    8/*_SPDRP_CLASSGUID*/,\n    0/*_SPDRP_DEVICEDESC*/\n    ) ){\n    __/*可用_SPDRP前缀的常量指定任意个查询字段,\n相应增加对应个数的迭代器返回值,但第一个迭代返回值总是表示位置索引\n最后一个迭代返回值总是当前设备的 SP_DEVINFO_DATA 结构体*/\n\n}
!stdSysDevice.destroy() = 删除设备列表\n此函数不是必须调用,内存回收器会自动调用此函数
sys.device.manager() = 打开设备管理器
_SPDRP_DEVICEDESC=@0/*_SPDRP_DEVICEDESC*/
_SPDRP_HARDWAREID=@1/*_SPDRP_HARDWAREID*/
_SPDRP_COMPATIBLEIDS=@2/*_SPDRP_COMPATIBLEIDS*/
_SPDRP_UNUSED0=@3/*_SPDRP_UNUSED0*/
_SPDRP_SERVICE=@4/*_SPDRP_SERVICE*/
_SPDRP_UNUSED1=@5/*_SPDRP_UNUSED1*/
_SPDRP_UNUSED2=@6/*_SPDRP_UNUSED2*/
_SPDRP_CLASS=@7/*_SPDRP_CLASS*/
_SPDRP_CLASSGUID=@8/*_SPDRP_CLASSGUID*/
_SPDRP_DRIVER=@9/*_SPDRP_DRIVER*/
_SPDRP_CONFIGFLAGS=@0xA/*_SPDRP_CONFIGFLAGS*/
_SPDRP_MFG=@0xB/*_SPDRP_MFG*/
_SPDRP_FRIENDLYNAME=@0xC/*_SPDRP_FRIENDLYNAME*/
_SPDRP_LOCATION_INFORMATION=@0xD/*_SPDRP_LOCATION_INFORMATION*/
_SPDRP_PHYSICAL_DEVICE_OBJECT_NAME=@0xE/*_SPDRP_PHYSICAL_DEVICE_OBJECT_NAME*/
_SPDRP_CAPABILITIES=@0xF/*_SPDRP_CAPABILITIES*/
_SPDRP_UI_NUMBER=@0x10/*_SPDRP_UI_NUMBER*/
_SPDRP_UPPERFILTERS=@0x11/*_SPDRP_UPPERFILTERS*/
_SPDRP_LOWERFILTERS=@0x12/*_SPDRP_LOWERFILTERS*/
_SPDRP_BUSTYPEGUID=@0x13/*_SPDRP_BUSTYPEGUID*/
_SPDRP_LEGACYBUSTYPE=@0x14/*_SPDRP_LEGACYBUSTYPE*/
_SPDRP_BUSNUMBER=@0x15/*_SPDRP_BUSNUMBER*/
_SPDRP_ENUMERATOR_NAME=@0x16/*_SPDRP_ENUMERATOR_NAME*/
_SPDRP_SECURITY=@0x17/*_SPDRP_SECURITY*/
_SPDRP_SECURITY_SDS=@0x18/*_SPDRP_SECURITY_SDS*/
_SPDRP_DEVTYPE=@0x19/*_SPDRP_DEVTYPE*/
_SPDRP_EXCLUSIVE=@0x1A/*_SPDRP_EXCLUSIVE*/
_SPDRP_CHARACTERISTICS=@0x1B/*_SPDRP_CHARACTERISTICS*/
_SPDRP_ADDRESS=@0x1C/*_SPDRP_ADDRESS*/
_SPDRP_UI_NUMBER_DESC_FORMAT=@0x1D/*_SPDRP_UI_NUMBER_DESC_FORMAT*/
_SPDRP_DEVICE_POWER_DATA=@0x1E/*_SPDRP_DEVICE_POWER_DATA*/
_SPDRP_REMOVAL_POLICY=@0x1F/*_SPDRP_REMOVAL_POLICY*/
_SPDRP_REMOVAL_POLICY_HW_DEFAULT=@0x20/*_SPDRP_REMOVAL_POLICY_HW_DEFAULT*/
_SPDRP_REMOVAL_POLICY_OVERRIDE=@0x21/*_SPDRP_REMOVAL_POLICY_OVERRIDE*/
_SPDRP_INSTALL_STATE=@0x22/*_SPDRP_INSTALL_STATE*/
_SPDRP_LOCATION_PATHS=@0x23/*_SPDRP_LOCATION_PATHS*/
_SPDRP_BASE_CONTAINERID=@0x24/*_SPDRP_BASE_CONTAINERID*/
_SPDRP_MAXIMUM_PROPERTY=@0x25/*_SPDRP_MAXIMUM_PROPERTY*/
end intellisense**/

	/**intellisense()
_GUID_DEVCLASS_1394=@"{6BDD1FC1-810F-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_1394DEBUG=@"{66F250D6-7801-4A64-B139-EEA80A450B24}"
_GUID_DEVCLASS_61883=@"{7EBEFBC0-3200-11D2-B4C2-00A0C9697D07}"
_GUID_DEVCLASS_ADAPTER=@"{4D36E964-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_APMSUPPORT=@"{D45B1C18-C8FA-11D1-9F77-0000F805F530}"
_GUID_DEVCLASS_AVC=@"{C06FF265-AE09-48F0-812C-16753D7CBA83}"
_GUID_DEVCLASS_BATTERY=@"{72631E54-78A4-11D0-BCF7-00AA00B7B32A}"
_GUID_DEVCLASS_BIOMETRIC=@"{53D29EF7-377C-4D14-864B-EB3A85769359}"
_GUID_DEVCLASS_BLUETOOTH=@"{E0CBF06C-CD8B-4647-BB8A-263B43F0F974}"
_GUID_DEVCLASS_CDROM=@"{4D36E965-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_COMPUTER=@"{4D36E966-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_DECODER=@"{6BDD1FC2-810F-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_DISKDRIVE=@"{4D36E967-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_DISPLAY=@"{4D36E968-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_DOT4=@"{48721B56-6795-11D2-B1A8-0080C72E74A2}"
_GUID_DEVCLASS_DOT4PRINT=@"{49CE6AC8-6F86-11D2-B1E5-0080C72E74A2}"
_GUID_DEVCLASS_ENUM1394=@"{C459DF55-DB08-11D1-B009-00A0C9081FF6}"
_GUID_DEVCLASS_FDC=@"{4D36E969-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_FLOPPYDISK=@"{4D36E980-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_GPS=@"{6BDD1FC3-810F-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_HDC=@"{4D36E96A-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_HIDCLASS=@"{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}"
_GUID_DEVCLASS_IMAGE=@"{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_INFINIBAND=@"{30EF7132-D858-4A0C-AC24-B9028A5CCA3F}"
_GUID_DEVCLASS_INFRARED=@"{6BDD1FC5-810F-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_KEYBOARD=@"{4D36E96B-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_LEGACYDRIVER=@"{8ECC055D-047F-11D1-A537-0000F8753ED1}"
_GUID_DEVCLASS_MEDIA=@"{4D36E96C-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MEDIUM_CHANGER=@"{CE5939AE-EBDE-11D0-B181-0000F8753EC4}"
_GUID_DEVCLASS_MEMORY=@"{5099944A-F6B9-4057-A056-8C550228544C}"
_GUID_DEVCLASS_MODEM=@"{4D36E96D-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MONITOR=@"{4D36E96E-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MOUSE=@"{4D36E96F-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MTD=@"{4D36E970-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MULTIFUNCTION=@"{4D36E971-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_MULTIPORTSERIAL=@"{50906CB8-BA12-11D1-BF5D-0000F805F530}"
_GUID_DEVCLASS_NET=@"{4D36E972-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_NETCLIENT=@"{4D36E973-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_NETSERVICE=@"{4D36E974-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_NETTRANS=@"{4D36E975-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_NODRIVER=@"{4D36E976-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_PCMCIA=@"{4D36E977-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_PNPPRINTERS=@"{4658EE7E-F050-11D1-B6BD-00C04FA372A7}"
_GUID_DEVCLASS_PORTS=@"{4D36E978-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_PRINTER=@"{4D36E979-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_PRINTERUPGRADE=@"{4D36E97A-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_PROCESSOR=@"{50127DC3-0F36-415E-A6CC-4CB3BE910B65}"
_GUID_DEVCLASS_SBP2=@"{D48179BE-EC20-11D1-B6B8-00C04FA372A7}"
_GUID_DEVCLASS_SCSIADAPTER=@"{4D36E97B-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_SECURITYACCELERATOR=@"{268C95A1-EDFE-11D3-95C3-0010DC4050A5}"
_GUID_DEVCLASS_SENSOR=@"{5175D334-C371-4806-B3BA-71FD53C9258D}"
_GUID_DEVCLASS_SIDESHOW=@"{997B5D8D-C442-4F2E-BAF3-9C8E671E9E21}"
_GUID_DEVCLASS_SMARTCARDREADER=@"{50DD5230-BA8A-11D1-BF5D-0000F805F530}"
_GUID_DEVCLASS_SOUND=@"{4D36E97C-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_SYSTEM=@"{4D36E97D-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_TAPEDRIVE=@"{6D807884-7D21-11CF-801C-08002BE10318}"
_GUID_DEVCLASS_UNKNOWN=@"{4D36E97E-E325-11CE-BFC1-08002BE10318}"
_GUID_DEVCLASS_USB=@"{36FC9E60-C465-11CF-8056-444553540000}"
_GUID_DEVCLASS_VOLUME=@"{71A27CDD-812A-11D0-BEC7-08002BE2092F}"
_GUID_DEVCLASS_VOLUMESNAPSHOT=@"{533C5B84-EC70-11D2-9505-00C04F79DEAF}"
_GUID_DEVCLASS_WCEUSBS=@"{25DBCE51-6C8F-4A72-8A6D-B54C2B4FC835}"
_GUID_DEVCLASS_WPD=@"{EEC5AD98-8080-425F-922A-DABF3DE3F69A}"
_GUID_DEVCLASS_EHSTORAGESILO=@"{9DA2B80F-F89F-4A49-A5C2-511B085B9E8A}"
_GUID_DEVCLASS_FIRMWARE=@"{F2E7DD72-6468-4E36-B6F1-6488F42C1B52}"
_GUID_DEVCLASS_EXTENSION=@"{E2F84CE7-8EFA-411C-AA69-97454CA4CB57}"
end intellisense**/