C/C++注册表【3】子键枚举,备份,恢复

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunjikui1255326447/article/details/88821868

C/C++注册表【2】子键枚举,备份,恢复

(1)子键信息获取

RegQueryInfoKey(

        hkey,            //要获取信息的句柄

        lpClass,        //接受创建健时的Class字符串

        lpcbClass,        //lpClass的长度

        lpReserved,        //系统保留,指定为0

        lpcSubKeys,        //子键数量

        lpcbMaxSubKeyLen,    //子键中最长名称的长度

        lpcbMaxClassLen,    //子键中最长Class字符串长度

        lpcVlaues,        //键值数量

        lpcbMaxValueNameLen,    //键值项中最长名称的长度

        lpcbMaxValueLen,    //键值项数据最大长度

        lpcbSecurityDescriptor,    //安全描述符长度

        lpftLastWriteTime,    //FILETIME结构,最后修改时间

        );

这个函数的参数很多,实际使用时,只填写自己需要的就行了,不需要的可以放个NULL就OK了,还有一点需要注意就是它所返回的长度都不包括结尾的0字符,所以在使用时应该用长度+1。

#include "pch.h"
#include <iostream>
#include "Regtest.h"
#include <windows.h>
#include <Tchar.h>
Regtest::Regtest()
{
}

Regtest::~Regtest()
{
}

int main() {
	HKEY hKey = NULL;
	const TCHAR *lpszSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
	LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
	if (lRet == ERROR_SUCCESS) {
		DWORD dwSubKeys = 0, maxSubKeyLen = 0, dwValueCount = 0, maxValueNameLen = 0, maxValueDataLen = 0;
		lRet = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &maxSubKeyLen, NULL, &dwValueCount, &maxValueNameLen, &maxValueDataLen, NULL, NULL);
		if (lRet == ERROR_SUCCESS) {
			printf("success");
		}
	}
}

2、枚举子键信息

RegEnumKeyEx(

        hkey,        //被枚举的键句柄

        dwIndex,    //子键索引编号

        lpName,        //子键名称

        lpcbName,    //子键名称长度

        lpReserved,    //系统保留,指定为0

        lpClass,    //子键类名

        lpcbClass,    //子键类名长度

        lpftLastWriteTime//最后写入时间

        );

因为在之前我们已经通过RegQueryInfoKey函数获取了键的有关数据,所以在这里不再跟据ERROR_NO_MORE_ITEMS来实现了。

#include "pch.h"
#include <iostream>
#include "Regtest.h"
#include <windows.h>
#include <Tchar.h>
Regtest::Regtest()
{
}

Regtest::~Regtest()
{
}

int main() {
	HKEY hKey = NULL;
	const TCHAR *lpszSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Reliability");
	LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
	if (lRet == ERROR_SUCCESS) {
		DWORD dwSubKeys = 0, maxSubKeyLen = 0, dwValueCount = 0, maxValueNameLen = 0, maxValueDataLen = 0;
		lRet = RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwSubKeys, &maxSubKeyLen, NULL, &dwValueCount, &maxValueNameLen, &maxValueDataLen, NULL, NULL);
		if (lRet == ERROR_SUCCESS) {
			//Enum for the sub keys
			DWORD dwNameLen = maxSubKeyLen + 1;
			TCHAR *pszName = new TCHAR[maxSubKeyLen + 1];
			for (DWORD dwIndex = 0; dwIndex < dwSubKeys; ++dwIndex) {

				ZeroMemory(pszName, dwNameLen);
				dwNameLen = maxSubKeyLen + 1; //※※※

				RegEnumKeyEx(hKey, dwIndex, pszName, &dwNameLen, NULL, NULL, NULL, NULL);
				//Other operations
			}
			delete[] pszName;
		}
		RegCloseKey(hKey);
	}
}

3、备份/恢复注册表

 备份和恢复注册表相对来说用的不是太多,仅用一个运行在CONSOLE32下的小程序来讨论一下它们的实现。

 备份注册表可以用RegSaveKey函来实现, 它的原形如下:

 RegSaveKey(

        hkey,            //要备份的键句柄

        lpFile,        //保存信息的文件名称

        lpSecurityAttributes    //文件安全属性

        );

hkey为要备份的键句柄,可以是系统预定义的,也可以是用RegOpenKey()打开或是RegCreateKeyEx()创建的。

lpFile为保存信息的文件名称,注意这个文件必须是不存在的,而且也不能有扩展名(否则RegRestoreKey()函无法读取)。

lpSecurityAttributes:在NT系统中用来设置新文件的安全属性,通常设置为NULL。

在使用这个函数时需要有SE_BACKUP_NAME权限,而这个权限是不可以在RegOpenKey()或是RegCreateKeyEx()中指定的。

#include "pch.h"
#include <iostream>
#include "Regtest.h"
#include <windows.h>
#include <Tchar.h>
BOOL EnableTargetPriv(LPTSTR lpszPrivilege);
int main() {

	HKEY hKey = NULL;
	const TCHAR *lpszSubKey = _T("SOFTWARE\\Runtest");
	EnableTargetPriv(LPTSTR(SE_BACKUP_NAME));
	LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
	if (lRet == ERROR_SUCCESS) {
		lRet = RegSaveKey(hKey, _T("D:\\123"), NULL);
		RegCloseKey(hKey);
	}

	return 0;

}
BOOL EnableTargetPriv(LPTSTR lpszPrivilege)
{
	HANDLE hToken = NULL;
	TOKEN_PRIVILEGES tkp = { 0 };
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		return FALSE;
	}
	if (!LookupPrivilegeValue(NULL, lpszPrivilege, &tkp.Privileges[0].Luid)) {
		CloseHandle(hToken);
		return FALSE;
	}
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
		CloseHandle(hToken);
		return FALSE;
	}
	return TRUE;
}

可以看到注册表备份成功----------------------》如下图

恢复注册表可以用函数RegRestoreKey来实现,它的原形如下:

RegRestoreKey(

        hkey,            //要恢复的键句柄

        lpFile,        //保存信息的文件名称

        dwFlage        //标志是否易失

        );  

恢复注册表代码如下:

#include "pch.h"
#include <iostream>
#include "Regtest.h"
#include <windows.h>
#include <Tchar.h>
Regtest::Regtest()
{
}

Regtest::~Regtest()
{
}
BOOL EnableTargetPriv(LPTSTR lpszPrivilege);


int main() {

	HKEY hKey = NULL;
	const TCHAR *lpszSubKey = _T("SOFTWARE\\Runtest");
	EnableTargetPriv(LPTSTR(SE_RESTORE_NAME));
	LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
	if (lRet == ERROR_SUCCESS) {
		LPCTSTR lpszFile = _T("D:\\123");
		lRet = RegRestoreKey(hKey, lpszFile, REG_FORCE_RESTORE);
		RegCloseKey(hKey);
	}
	return 0;
}
BOOL EnableTargetPriv(LPTSTR lpszPrivilege)
{
	HANDLE hToken = NULL;
	TOKEN_PRIVILEGES tkp = { 0 };
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		return FALSE;
	}
	if (!LookupPrivilegeValue(NULL, lpszPrivilege, &tkp.Privileges[0].Luid)) {
		CloseHandle(hToken);
		return FALSE;
	}
	tkp.PrivilegeCount = 1;
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
		CloseHandle(hToken);
		return FALSE;
	}
	return TRUE;
}

猜你喜欢

转载自blog.csdn.net/sunjikui1255326447/article/details/88821868