想必注册表大家都不陌生,微软自然也提供了注册表操作的API,通过这些API,我们可以修改注册表达到很多目的,比如添加关联,修改系统设置等。
注意:绝大多数的注册表键的ACL都是不允许标准用户权限的程序写入的,因此,请使用管理员权限运行程序。
一。基本感念:
1。键(项),值项
注册表编辑器左侧的那些文件树中的每个都叫“键”(也叫项),右侧的那些叫值项(也可叫“键值”)。
子键(子项):一个键下面的分支
2。数据类型:
REG_SZ:字符串
REG_MULTI_SZ:多字符串
REG_BINARY :二进制数
REG_DWORD :这个就不用我说了吧,看名字就知道是DWORD
(typedef unsigned long DWORD;)
更多数据类型参见MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx
二。关于WOW64的问题:
32位程序运行在64位系统上操作注册表会出现问题,在下面会有说明。
三。创建注册表键
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724844(v=vs.85).aspx
函数原型:
LONG WINAPI RegCreateKeyEx(
_In_ HKEY hKey,
_In_ LPCTSTR lpSubKey,
_Reserved_ DWORD Reserved,
_In_opt_ LPTSTR lpClass,
_In_ DWORD dwOptions,
_In_ REGSAM samDesired,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_Out_ PHKEY phkResult,
_Out_opt_ LPDWORD lpdwDisposition
);
提示:这个也可以用来打开一项。
hKey:要打开键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
lpSubKey:要创建的子键的名称
Reserved:必须为0
lpClass:置NULL
dwOptions:一般用不到,为0即可
samDesired:访问权限,创建一般用不到,为0即可;打开的权限参见“四。打开注册表键”(对于64位系统上运行的32位程序,即WOW64环境,此参数应该有KEY_WOW64_64KEY,才能正常访问注册表,可以使用一个叫IsWow64Process的函数判断当前环境是否为WOW64)
lpSecurityAttributes: 确定是否可以由子进程继承返回的句柄的SECURITY_ATTRIBUTES 结构的指针。如果 lpSecurityAttributes 为 NULL,该句柄不能被继承。
一般置NULL即可
phkResult:一个用于接收句柄的指针
lpdwDisposition:一个用于接收结果的指针
可能的结果有:REG_CREATED_NEW_KEY创建成功;REG_OPENED_EXISTING_KEY:键已存在
返回值:成功返回ERROR_SUCCESS
四。打开注册表键
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724897(v=vs.85).aspx
函数原型:
LONG WINAPI RegOpenKeyEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpSubKey,
_In_ DWORD ulOptions,
_In_ REGSAM samDesired,
_Out_ PHKEY phkResult
);
hKey:要打开键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
lpSubKey:要打开的子键的名称
ulOptions:一般为0
samDesired:访问权限(对于64位系统上运行的32位程序,即WOW64环境,此参数应该具有KEY_WOW64_64KEY,才能正常访问注册表,可以使用一个叫IsWow64Process的函数判断当前环境是否为WOW64)
KEY_ALL_ACCESS:所有权限
KEY_CREATE_SUB_KEY:需要创建注册表项的子项。
KEY_ENUMERATE_SUB_KEYS:所需枚举注册表项的子项。
KEY_EXECUTE:相当于 KEY_READ。
KEY_NOTIFY:所需要求更改通知的某个注册表项或注册表项的子项。
KEY_QUERY_VALUE:所需查询注册表项的值。
KEY_READ:结合STANDARD_RIGHTS_READ、 KEY_QUERY_VALUE、 KEY_ENUMERATE_SUB_KEYS 和 KEY_NOTIFY
KEY_SET_VALUE:需要创建、 删除或设置注册表值。
KEY_WRITE:结合STANDARD_RIGHTS_WRITE、KEY_SET_VALUE 和 KEY_CREATE_SUB_KEY
phkResult:一个用于接收句柄的指针
返回值:成功返回ERROR_SUCCESS
五。删除注册表键
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724845(v=vs.85).aspx
函数原型:
LONG WINAPI RegDeleteKey(
_In_ HKEY hKey,
_In_ LPCTSTR lpSubKey
);
hKey:要删除键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
lpSubKey:要删除的子键的名称
返回值:成功返回ERROR_SUCCESS
六。创建/修改值项
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724923(v=vs.85).aspx
函数原型:
LONG WINAPI RegSetValueEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpValueName,
_Reserved_ DWORD Reserved,
_In_ DWORD dwType,
_In_ const BYTE *lpData,
_In_ DWORD cbData
);
hKey:要打开键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
lpValueName:要创建、打开的键值的名称
Reserved:必须为0
dwType:数据类型(参见上面的说明)
lpData:要存储的数据。对于基于字符串的类型,例如 REG_SZ,字符串必须是 null 终止。与 REG_MULTI_SZ 数据类型,字符串必须终止与两个 null 字符。
cbData:指 lpData 参数,以字节为单位的信息的大小。如果数据类型为 REG_SZ,REG_EXPAND_SZ 或 REG_MULTI_SZ,cbData 必须包括终止 null 字符或字符的大小。
返回值:成功返回ERROR_SUCCESS
七。读取值项
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724911(v=vs.85).aspx
函数原型:
LONG WINAPI RegQueryValueEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpValueName,
_Reserved_ LPDWORD lpReserved,
_Out_opt_ LPDWORD lpType,
_Out_opt_ LPBYTE lpData,
_Inout_opt_ LPDWORD lpcbData
);
hKey:要读取键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_PERFORMANCE_DATA
HKEY_PERFORMANCE_NLSTEXT
HKEY_PERFORMANCE_TEXT
HKEY_USERS
lpValueName:要读取的键值的名称
lpReserved:必须为NULL
lpType:数据类型(参见上面的说明)
lpData:接收数据的缓冲区指针
lpcbData:要接收的长度
返回值:
如果此函数成功,返回值是ERROR_SUCCESS
如果 lpData 缓冲区太小,无法接收数据,则函数返回ERROR_MORE_DATA
如果 lpValueName 注册表值不存在,则函数返回 ERROR_FILE_NOT_FOUND。
八。删除值项
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724851(v=vs.85).aspx
函数原型:
LONG WINAPI RegDeleteValue(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpValueName
);
hKey:要删除键的句柄或以下预定义句柄
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
lpValueName:要删除的键值的名称
返回值:成功返回ERROR_SUCCESS
九。关闭句柄
键句柄使用完成后,应使用RegCloseKey关闭句柄,释放资源
MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724837(v=vs.85).aspx
函数原型:
LONG WINAPI RegCloseKey(
_In_ HKEY hKey
);
hKey:要关闭的键句柄
返回值:成功返回ERROR_SUCCESS
例子:利用注册表实现开机自启动
#include <stdio.h>
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
LPCTSTR path = TEXT("程序路径");
//判断环境是否为WOW64
BOOL isWOW64;
REGSAM p;
IsWow64Process(GetCurrentProcess(),&isWOW64);
if (isWOW64){
p = KEY_WRITE | KEY_WOW64_64KEY;
}
else{
p = KEY_WRITE;
}
HKEY hKey;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, NULL, 0, p, NULL, &hKey, NULL) != ERROR_SUCCESS){
//失败
return 0;
}
if (RegSetValueEx(hKey, TEXT("这里设置一个你喜欢的值_不能和其他程序重了"), 0, REG_SZ, (BYTE*)path, sizeof(path)*sizeof(TCHAR))!= ERROR_SUCCESS){
//失败
return 0;
}
RegCloseKey(hKey);
return 0;
}
效果图:
(汗,那个QQ游戏是俺老爸装的,俺不玩游戏)
PS:关于枚举子键和枚举值项的方法,且听下回分解。