C/C++注册表【2】子键枚举,备份,恢复
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
#include "Regtest.h"
#include
#include
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");
}
}
}
RegEnumKeyEx(
hkey, //被枚举的键句柄
dwIndex, //子键索引编号
lpName, //子键名称
lpcbName, //子键名称长度
lpReserved, //系统保留,指定为0
lpClass, //子键类名
lpcbClass, //子键类名长度
lpftLastWriteTime//最后写入时间
);
因为在之前我们已经通过RegQueryInfoKey函数获取了键的有关数据,所以在这里不再跟据ERROR_NO_MORE_ITEMS来实现了。
#include "pch.h"
#include
#include "Regtest.h"
#include
#include
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);
}
}
备份和恢复注册表相对来说用的不是太多,仅用一个运行在CONSOLE32下的小程序来讨论一下它们的实现。
备份注册表可以用RegSaveKey函来实现, 它的原形如下:
RegSaveKey(
hkey, //要备份的键句柄
lpFile, //保存信息的文件名称
lpSecurityAttributes //文件安全属性
);
hkey为要备份的键句柄,可以是系统预定义的,也可以是用RegOpenKey()打开或是RegCreateKeyEx()创建的。
lpFile为保存信息的文件名称,注意这个文件必须是不存在的,而且也不能有扩展名(否则RegRestoreKey()函无法读取)。
lpSecurityAttributes:在NT系统中用来设置新文件的安全属性,通常设置为NULL。
在使用这个函数时需要有SE_BACKUP_NAME权限,而这个权限是不可以在RegOpenKey()或是RegCreateKeyEx()中指定的。
#include "pch.h"
#include
#include "Regtest.h"
#include
#include
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
#include "Regtest.h"
#include
#include
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;
}