//reg 注册表操作
namespace win; 

class reg{
	ctor( rpath , check ,root){
		assert(type(rpath) == type.string ,"注册表路径必须是字符串对象")
		if(!root){
			this.path = rpath;
			var sep = ..string.indexAny( rpath,"\" ); 
			if(sep){
				var lpath = ..string.left(rpath,sep-1);
				rpath = ..string.sub(rpath,sep+1) 
				root = assert( hkey[lpath],'错误的注册表路径\n注册表路径必须使用斜杠"\\"分隔路径'); 
			}
			else{
	   			this.m_key = hkey[rpath]
	   			assert( this.m_key,"错误的注册表路径");  
			}
		}
		 
		if(not this.m_key){
			var re,tempkey = (check?RegOpenKey:RegCreateKey)( root ,rpath ,0);
     		if (re != 0/*_ERROR_SUCCESS*/ )
        		return null,"打开注册表出错!";
     		 
        	this.m_key = tempkey; 
        }
        
	}
	openReg = function(subpath, check ){
		reg =  ..win.reg(subpath,check,this.m_key);
		reg.path =  ..string.concat(this.path , "\" , subpath);
		return reg;
	}  
	
	eachKey = function(len=256){ 
		var index = 0;
		return function(){
		import win;
			var re,lpName,lpcbName,lpClass,lpcbClass,lpftLastWriteTime = RegEnumKeyEx(this.m_key,index,len,len,/*lpReserved*/, ,0, ::FILETIME() );
	 
			if (re != 0/*_ERROR_SUCCESS*/ )
				return null;
			index++;
			return ..string.str(lpName),lpftLastWriteTime;
		}
	
	}
	enumKey = function(proc,len=256){
		var tkeys ={};
		for(keyname,writetime in this.eachKey() ){
			//先取回所有的节点，防止回调函数删除节点，迭代器数字索引错位
			..table.push(tkeys,keyname);  
		}
		
		var subreg;
		for(i=1;#tkeys){
			subreg=this.openReg(tkeys[i]); 
			subreg.enumKey(proc,len);//迭代
			subreg.close();
			
			proc(this,tkeys[i]); 
		} 

	}
	eachValue = function (len = 256) {
		var index = 0;
		return function () {
			var re, valuename, valuenamelen, valuetype, data, datalen = RegEnumValue(this.m_key, index, len, len, , 0, len, len);
			
			if (re == 0x103/*_ERROR_NO_MORE_ITEMS*/)
				return null;
			
			if (valuetype == 4 || valuetype == 7)
				data = ..string.left(data, datalen);
			
			index++;
			return ..string.str(valuename), data, valuetype;
		}
	}
	
	
	setDwValue = function( name,value) {
    	// 写入注册表 name=null 则设置注册表默认值
		res=RegSetValueEx( this.m_key,name,0,REG_DWORD,{INT dw = value },4);
		return (res==0/*_ERROR_SUCCESS*/) ;
	}
	setQwValue = function( name,value,value2) {
    	// 写入注册表 name=null 则设置注册表默认值
		res=RegSetValueEx( this.m_key,name,0,REG_QWORD,{INT dw = value;INT dw2 = value2 },8);
		return (res==0/*_ERROR_SUCCESS*/) ;
	} 
	setSzValue = function( name,value)  {
    	// 写入注册表 name=null 则设置注册表默认值
		res=RegSetValueExString( this.m_key,name,0,REG_SZ,value,#value+1);
		return (res==0/*_ERROR_SUCCESS*/) ;
	}
	setMultiSzValue = function( name,...)  {
    	// 写入注册表 name=null 则设置注册表默认值
    	var t ={...};
    	var v = ..string.join(t,'\0');
    	if(  ..string.endWith( v,'\0\0') == false) v ++= '\0\0';
		res=RegSetValueExString( this.m_key,name,0,REG_MULTI_SZ,v,#v+1);
		return (res==0/*_ERROR_SUCCESS*/) ;
	}
	setBinValue = function( name,value) {
    	// 写入注册表 name=null 则设置注册表默认值
		res=RegSetValueExString( this.m_key,name,0,REG_BINARY,value,#value+1);
		return (res==0/*_ERROR_SUCCESS*/) ;
	}
	
	queryValue = function(name) {
 		// 从注册表中读取数据 
     	var r,t,len = RegQueryValueExLen( this.m_key,name,0,0,null,0);
     	
     	select(t) { 
     		case REG_SZ {
     			r,t,p,len = RegQueryValueExStr( this.m_key,name,0,0,len,len); 
     			return p,t;
     		}
     		case REG_DWORD {
     			r,t,p,len = RegQueryValueEx( this.m_key,name,0,0,{INT val },len);
     			return p.val,t;
     		}
     		case REG_MULTI_SZ,REG_BINARY,REG_EXPAND_SZ {
     			r,t,p,len = RegQueryValueExString( this.m_key,name,0,0,len,len); 
     			return p,t;
     		} 
     		case REG_QWORD {
     			r,t,p,len = RegQueryValueEx( this.m_key,name,0,0,{INT a;INT b },len);
     			return p ,t;
     		}   
     	}
     	return null;
 	}
 	 
	delValue = function(name) { 
		// 删除注册表的某个值
		var res=RegDeleteValue(this.m_key,name);
		return (res==0/*_ERROR_SUCCESS*/) 
	}
	
	delKey = function(name) { 
	// 删除注册表的某个值
	var res=RegDeleteKey(this.m_key,name);
	return (res==0/*_ERROR_SUCCESS*/) 
	}
	
	
	close = function(){
     	if (this.m_key)
     	{
         	RegCloseKey(this.m_key);
         	this.m_key=null;
     	}
	}
	
	save = function( filepath ){   
        setprivilege('SeBackupPrivilege',true)     
        ret = RegSaveKey(this.m_key, ..io.fullpath(filepath) );  
        return !ret   
  	
	}
	
	
	load = function(filepath){   
        setprivilege('SeRestorePrivilege',true)   
        ret = RegRestoreKey(this.m_key, ..io.fullpath(filepath) ,0x00000008/*_REG_FORCE_RESTORE*/  ) 
        return !ret  
  	
	}



}

//类有独立的名字空间
namespace reg{

	::FILETIME := class{ 
 	INT dwLowDateTime ;
 	INT dwHighDateTime ;
	} 
	
	//所有DLL变量约定首字母大写，并使用:=赋值操作符
	//通用DLL请使用::前缀，仅在一个名字空间使用的DLL不建议添加::前缀
	Advapi32 :=  ..raw.loadDll("Advapi32.dll")
	RegCreateKey = Advapi32.api("RegCreateKeyA","int(int hKey,string lpSubKey,int & phkResult)" );
	RegOpenKey = Advapi32.api("RegOpenKeyA","int(int hKey,string lpSubKey,int & phkResult)" ); 
	RegCloseKey = Advapi32.api("RegCloseKey","int(int hKey)" );
	RegDeleteValue = Advapi32.api("RegDeleteValue","int(int hKey,string lpValueName)" )
	RegDeleteKey = Advapi32.api("RegDeleteKeyA","int(int hKey,string lpSubKey)" )
 	
	RegSetValueEx = Advapi32.api("RegSetValueExA","int(int hKey,string lpValueName,INT Reserved,INT dwType,struct lpData,INT cbData)" ); 
	RegQueryValueEx = Advapi32.api("RegQueryValueExA","int(int hKey,string lpValueName,INT Reserved,INT &dwType,struct&lpData,INT&lpcbData)" ); 
	RegSetValueExString = Advapi32.api("RegSetValueExA","int(int hKey,string lpValueName,INT Reserved,INT dwType,string lpData,INT cbData)" ); 
	RegQueryValueExString = Advapi32.api("RegQueryValueExA","int(int hKey,string lpValueName,INT Reserved,INT &dwType,string&lpData,INT&lpcbData)" ); 
	RegQueryValueExStr = Advapi32.api("RegQueryValueExA","int(int hKey,string lpValueName,INT Reserved,INT &dwType,str&lpData,INT&lpcbData)" ); 
	RegQueryValueExLen = Advapi32.api("RegQueryValueExA","int(int hKey,string lpValueName,INT Reserved,INT &dwType,pointer lpData,INT&lpcbData)" ); 
 	
    RegSaveKey =  Advapi32.api("RegSaveKeyA","int(int hKey,string lpFile,pointer lpSecurityAttributes)")
    RegRestoreKey = Advapi32.api("RegRestoreKeyA","int(int hKey,string lpFile,int dwFlags)")
    
    RegEnumValue = Advapi32.api("RegEnumValueA","int(int hKey,int dwIndex,string &lpValueName,int& lpcbValueName,pointer lpReserved,int& lpType,string& lpData,int& lpcbData)")
    //string &lpClass改为string lpClass,暂不需要此参数
    RegEnumKeyEx = Advapi32.api("RegEnumKeyExA","int(int hKey,int dwIndex,string &lpName,int& lpcbName,pointer lpReserved,string  lpClass,int& lpcbClass,struct& lpftLastWriteTime)")
     
	REG_NONE = 0 ; // No value type
	REG_SZ = 1 ; // Unicode nul terminated string
	REG_EXPAND_SZ = 2 ; // Unicode nul terminated string
	REG_BINARY = 3 ; // Free form binary
	REG_DWORD = 4 ; // 32-bit number 
	REG_DWORD_BIG_ENDIAN = 5 ; // 32-bit number
	REG_LINK = 6 ; // Symbolic Link (unicode;
	REG_MULTI_SZ = 7 ; // Multiple Unicode strings
	REG_RESOURCE_LIST = 8 ; // Resource list in the resource map
	REG_FULL_RESOURCE_DESCRIPTOR = 9 ; // Resource list in the hardware description
	REG_RESOURCE_REQUIREMENTS_LIST = 10 ;
	REG_QWORD = 11 ; // 64-bit number 
	
	namespace  hkey{
		HKEY_CLASSES_ROOT=0x80000000;
		HKEY_CURRENT_USER=0x80000001;
		HKEY_LOCAL_MACHINE=0x80000002;
		HKEY_USERS=0x80000003;
		HKEY_PERFORMANCE_DATA=0x80000004;
		HKEY_PERFORMANCE_TEXT=0x80000050;
		HKEY_PERFORMANCE_NLSTEXT=0x80000060;
		HKEY_CURRENT_CONFIG=0x80000005;
		HKEY_DYN_DATA=0x80000006;
		HKEY_CURRENT_USER_LOCAL_SETTINGS=0x80000007;
	}   
}


/**intellisense()
win.reg("__") = 打开已存在或创建新的注册表路径
win.reg("__",true) = 仅仅打开存在的注册表路径，如果不存在返回null
!reg.setDwValue("__",) = 设置32位数值
!reg.setQwValue("__",) = 设置64位数值
!reg.setSzValue("__",) = 设置字符串值
!reg.path = 注册表路径
!reg.setMultiSzValue("__",) = 设置复合字符串值
!reg.setBinValue("__",) = 设置二进制值
!reg.queryValue("__") = 查询值
!reg.delValue("__") = 删除值
!reg.delKey("__") = 删除键
!reg.close() = 关闭注册表对象 
!reg.save("/backup__") = 导出注册表到文件
!reg.load("/backup__") = 从文件导入到注册表
!reg.openReg("__") = 打开已存在或创建新的子路径，\n返回新的win.reg对象，
!reg.openReg("__",true) = 仅仅打开已存在的子路径，\n返回新的win.reg对象，\n如果不存在返回null
!reg.eachKey = @for(keyname,writetime in reg.eachKey() ){
	subreg=reg.openReg(keyname); 
}
!reg.enumKey = @.enumKey(\n\n	function(\n		reg, /*这是某个子节点(win.reg对象)*/\n		keyname/*这是reg子节点的一个子项的名字*/\n	){  \n		if( reg.delKey(keyname)  )\n			io.print("删除" + keyname + "成功") \n	}  \n) 
!reg.eachValue = @for(valuename, data in reg.eachValue()) {
	__
}
?win.reg = !reg.
?.openReg = !reg.
?.openKey = !reg.
?.createKey = !reg. 
end intellisense**/
