导航:[首页]->[windows]->[注册表工具函数备份]
#include <Windows.h>
#include <tchar.h>
#include <string>
#include <Shlwapi.h>
#include <cassert>

#if defined _UNICODE || defined UNICODE
typedef std::wstring String;
#else
typedef std::string String;
#endif

#pragma comment(lib,"Shlwapi.lib")

class Reg
{
public:
	Reg() : m_handle_(NULL){}
	~Reg(){ this->Close(); }

	// Open/Close
	/*
	HKEY_CLASSES_ROOT
	HKEY_CURRENT_CONFIG
	HKEY_CURRENT_USER
	HKEY_LOCAL_MACHINE
	HKEY_USERS
	*/
	inline bool Open(HKEY hKey, const String& path)
	{
		return OpenImp(hKey, path, KEY_READ);
	}
	inline bool OpenWrite(HKEY hKey, const String& path)
	{
		return OpenImp(hKey, path, KEY_WRITE);
	}
	inline bool OpenReadWrite(HKEY hKey, const String& path)
	{
		return OpenImp(hKey, path, KEY_READ | KEY_WRITE);
	}
	inline void Close()
	{
		if (m_handle_)
		{
			RegCloseKey(m_handle_);
			m_handle_ = NULL;
		}
	}

	// CreateDir/DeleteDir
	inline bool CreateDir(const String& path)
	{
		HKEY hKey_;
		LONG ret_ = RegCreateKey(m_handle_,
			path.c_str(),
			&hKey_);
		if (!ret_)
		{
			RegCloseKey(hKey_);
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("CreateDir"), ret_);
		return false;
	}
	inline bool DeleteDir(const String& path)
	{
#if 0
		LONG ret_ = RegDeleteKey(m_handle_, path.c_str());
		if (!ret_)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("DeleteDir"), ret_);
		return false;
#else
		LSTATUS ret_ = SHDeleteKey(m_handle_, path.c_str());
		if (ret_ == ERROR_SUCCESS)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("SHDeleteKey"), ret_);
		return false;
#endif
	}
	bool CopyDir(const String& str, Reg& reg)
	{
		LSTATUS ret_ = SHCopyKey(m_handle_,
			str.c_str(),
			reg.m_handle_,
			0);
		if (ret_ == ERROR_SUCCESS)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("SHCopyKey"), ret_);
		return false;
	}
	bool StatDir(DWORD* dircnt,DWORD* filecnt,
		DWORD* dirmaxlen, DWORD* filemaxlen)
	{
		DWORD dircnt_ = 0, filecnt_ = 0;
		DWORD dirmaxlen_ = 0, filemaxlen_ = 0;
		LSTATUS ret_ = RegQueryInfoKey(
			m_handle_,
			NULL, NULL, NULL,
			&dircnt_,
			&dirmaxlen_, 
			NULL,
			&filecnt_,
			&filemaxlen_,
			NULL, NULL, NULL);
		if( ret_ == ERROR_SUCCESS)
		{
			if (dircnt) *dircnt = dircnt_;
			if (filecnt) *filecnt = filecnt_;
			if (dirmaxlen) *dirmaxlen = dirmaxlen_;
			if (filemaxlen) *filemaxlen = filemaxlen_;
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("RegQueryInfoKey"), ret_);
		return false;
	}
	bool GetSubDir(DWORD index,DWORD len,String* str)
	{
		assert(str);
		TCHAR* buf_ = new TCHAR[len + 1];
		LONG ret_ = RegEnumKey(
			this->m_handle_,
			index,
			buf_,
			(len + 1)*sizeof(TCHAR));
		if (!ret_)
		{
			*str = buf_;
			delete[] buf_;
			return true;
		}
		delete[] buf_;
		assert(ret_ != ERROR_MORE_DATA);
		_tprintf(_T("[%s] error [%u]\n"), _T("RegEnumKey"), ret_);
		return false;
	}
	bool GetSubFile(DWORD index, DWORD len, String* str,DWORD* type)
	{
		assert(str && type);
		DWORD len_ = (len + 1)*sizeof(TCHAR);
		TCHAR* buf_ = new TCHAR[len + 1];
		LONG ret_ = RegEnumValue(
			this->m_handle_,
			index,
			buf_,
			&len_,
			0,
			type,
			NULL,
			NULL);
		if (!ret_)
		{
			*str = buf_;
			delete[] buf_;
			return true;
		}
		delete[] buf_;
		assert(ret_ != ERROR_MORE_DATA);
		_tprintf(_T("[%s] error [%u]\n"), _T("RegEnumKey"), ret_);
		return false;
	}

	// pwd/cd
	inline const String& Pwd() const
	{
		return this->m_path_;
	}
	bool Goto(const String& path)
	{
		if (String::npos != path.find(_T('\\')))
		{
			_tprintf(_T("[%s] error path %s\n"), _T("Goto"),path.c_str());
			return false;
		}
		HKEY hKey_;
		LONG ret_ = RegOpenKeyEx(
			m_handle_,
			path.c_str(),
			0,
			this->m_desired_,
			&hKey_);
		if (!ret_)
		{
			this->Close();
			this->m_handle_ = hKey_;
			if (this->m_path_[this->m_path_.length() - 1] != _T('\\'))
			{
				this->m_path_ += _T('\\');
			}
			this->m_path_ += path;
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("RegOpenKeyEx"), ret_);
		return false;
	}
	bool GotoParent()
	{
		size_t pos_ = this->m_path_.rfind(_T('\\'));
		if (pos_ == String::npos)
		{
			_tprintf(_T("[%s] error path %s\n"), 
				_T("GotoParent"),
				m_path_.c_str());
			return false;
		}
		String newpath_ = m_path_.substr(0, pos_);
		return OpenImp(m_root_, newpath_, m_desired_);
	}

	// create/edit
	bool Write(const String& key, DWORD value)
	{
		LONG ret_ = RegSetValueEx(
			this->m_handle_,
			key.c_str(),
			0,
			REG_DWORD,
			(const BYTE*)&value,
			sizeof(value));
		if (!ret_)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("RegSetValue"), ret_);
		return false;
	}
	bool Write(const String& key, const String& str)
	{
		LONG ret_ = RegSetValueEx(
			this->m_handle_,
			key.c_str(),
			0,
			REG_SZ,
			(const BYTE*)str.c_str(),
			(str.size() + 1)*sizeof(TCHAR));
		if (!ret_)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("RegSetValue"), ret_);
		return false;
	}
	bool Read(const String& key, DWORD* value)
	{
		assert(value);
		DWORD type_ = 0;
		DWORD len_ = sizeof(*value);
		LONG ret_ = RegQueryValueEx(
			this->m_handle_,
			key.c_str(),
			0,
			&type_,
			(LPBYTE)value,
			&len_);
		if (!ret_ && len_ == sizeof(*value) && type_ == REG_DWORD)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u|%u|%u]\n"), 
			_T("RegQueryValueEx"), ret_,len_,type_);
		return false;
	}
	bool Read(const String& key, String* value)
	{
		assert(value);
		DWORD type_ = 0;
		DWORD len_ = 0;
		LONG ret_ = RegQueryValueEx(
			this->m_handle_,
			key.c_str(),
			0,
			&type_,
			NULL,
			&len_);
		if (!ret_ && type_ == REG_SZ)
		{
			assert(len_%sizeof(TCHAR) == 0);
			TCHAR* ptr_ = new TCHAR[len_ / sizeof(TCHAR)];
			ret_ = RegQueryValueEx(
				this->m_handle_,
				key.c_str(),
				0,
				&type_,
				(LPBYTE)ptr_,
				&len_);
			if (!ret_)
			{
				*value = ptr_;
				delete[] ptr_;
				return true;
			}
			delete[] ptr_;
		}
		_tprintf(_T("[%s] error [%u|%u|%u]\n"),
			_T("RegQueryValueEx"), ret_, len_, type_);
		return false;
	}
	bool Stat(const String& key,DWORD* type,DWORD* len)
	{
		assert(type && len);
		LONG ret_ = RegQueryValueEx(
			this->m_handle_,
			key.c_str(),
			0,
			type,
			NULL,
			len);
		if (!ret_)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u|%u|%u]\n"),
			_T("RegQueryValueEx"), ret_, *len, *type);
		return false;
	}
	// delete
	bool Delete(const String& key)
	{
		size_t pos_ = key.rfind(_T('\\'));
		if (pos_ != String::npos)
		{
			_tprintf(_T("[%s] error path %s\n"),
				_T("Delete"),
				m_path_.c_str());
			return false;
		}
		LONG ret_ = RegDeleteValue(
			this->m_handle_,
			key.c_str());
		if (!ret_)
		{
			return true;
		}
		_tprintf(_T("[%s] error [%u]\n"), _T("RegDeleteKey"), ret_);
		return false;
	}
private:
	bool OpenImp(HKEY hKey, const String& path, REGSAM desired)
	{
		LONG ret_ = RegOpenKeyEx(
			hKey,
			path.c_str(),
			0,
			desired,
			&m_handle_);
		if (!ret_)
		{
			this->m_path_ = path;
			this->m_desired_ = desired;
			this->m_root_ = hKey;
			return true;
		}
		m_handle_ = NULL;
		_tprintf(_T("[%s] error [%u]\n"), _T("RegOpenKeyEx"), ret_);
		return false;
	}
private:
	HKEY m_root_;
	HKEY m_handle_;
	REGSAM m_desired_;
	String m_path_;
};

int _tmain(int argc, _TCHAR* argv[])
{
	Reg reg_;
	if (!reg_.OpenReadWrite(HKEY_CURRENT_USER, _T("Software\\Tiled")))
		return -1;
	assert(reg_.CreateDir(_T("fuck")));
	_tprintf(_T("[%s] [%s]\n"), _T("PWD"), reg_.Pwd().c_str());

	assert(reg_.Write(_T("fuck"), 1234));
	assert(reg_.Goto(_T("fuck")));
	assert(reg_.Write(_T("fuck"), 12345));
	assert(reg_.Write(_T("fuck"), 123456));
	DWORD ret_;
	assert(reg_.Read(_T("fuck"), &ret_));
	_tprintf(_T("Read [%u]\n"), ret_);
	assert(reg_.Write(_T("str"), _T("FUCK")));
	String str_;
	assert(reg_.Read(_T("str"), &str_));
	_tprintf(_T("[%s] [%s]\n"), _T("Read"), str_.c_str());
	assert(reg_.Delete(_T("fuck")));
	assert(reg_.Delete(_T("str")));
	assert(reg_.GotoParent());
	assert(reg_.Delete(_T("fuck")));
	_tprintf(_T("[%s] [%s]\n"), _T("PWD"), reg_.Pwd().c_str());
	assert(reg_.DeleteDir(_T("fuck")));

	Reg reg2_;
	if (!reg2_.OpenReadWrite(HKEY_CURRENT_USER, _T("Software\\Thunder Network")))
		return -1;
	assert(reg_.CreateDir(_T("fuck\\fuck1")));
	assert(reg_.Goto(_T("fuck")));
	assert(reg_.Goto(_T("fuck1")));
	assert(reg_.Write(_T("str"), _T("FUCK")));
	assert(reg_.Write(_T("fuck"), 123456));
	assert(reg_.GotoParent());
	assert(reg_.GotoParent());
	assert(reg_.CopyDir(_T("fuck"), reg2_));
	assert(reg_.DeleteDir(_T("fuck")));
	DWORD dircnt_, filecnt_, dirmaxlen_, filemaxlen_;
	assert(reg2_.StatDir(&dircnt_, &filecnt_, &dirmaxlen_, &filemaxlen_));
	for (DWORD i = 0; i < dircnt_; i++)
	{
		String dirname_;
		assert(reg2_.GetSubDir(i, dirmaxlen_, &dirname_));
		_tprintf(_T("dirname %s\n"), dirname_.c_str());
	}
	for (DWORD i = 0; i < filecnt_; i++)
	{
		String filename_;
		DWORD type_;
		assert(reg2_.GetSubFile(i, filemaxlen_, &filename_, &type_));
		_tprintf(_T("filename %s %d\n"), filename_.c_str(),type_);
	}
	assert(reg2_.DeleteDir(_T("fuck1")));
	return 0;
}