RegSetValueEx返回998(ERROR_NOACCESS),内存访问无效问题排查
RegSetValueEx返回ERROR_NOACCESS(998)的问题排查与修复
核心问题:数据长度参数错误
你调用RegSetValueEx时最后一个参数传了0,这是致命错误。对于REG_SZ类型的宽字符串(WCHAR),cbData参数必须指定包含终止符\0在内的总字节数。系统需要这个长度来正确读取字符串内容,传0的话,系统会尝试读取无效的内存区域,直接触发ERROR_NOACCESS。
正确的长度计算方式是:(wcslen(path) + 1) * sizeof(WCHAR),其中+1是为了包含末尾的宽字符终止符。
次要问题:权限与错误检查缺失
- 注册表权限过度申请:用
KEY_ALL_ACCESS打开HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run完全没必要,普通用户甚至会因为权限不足导致RegOpenKeyExW失败,后续操作无效的键句柄也会引发异常。只需要申请KEY_SET_VALUE权限即可满足写入需求。 - 无错误检查:代码里没检查
VirtualAlloc、GetModuleFileNameW、RegOpenKeyExW的返回值——如果这些操作失败,后续使用无效指针或键句柄都会导致未定义行为,包括内存访问错误。
修复后的代码示例
LPWSTR path = (LPWSTR)VirtualAlloc(nullptr, MAX_PATH * 2 * sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); if (!path) { // 处理内存分配失败 return; } DWORD copyLen = GetModuleFileNameW(nullptr, path, MAX_PATH); if (copyLen == 0 || copyLen == MAX_PATH) { // 处理路径获取失败或路径被截断 VirtualFree(path, 0, MEM_RELEASE); return; } HKEY key; LSTATUS openStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &key); if (openStatus != ERROR_SUCCESS) { // 处理注册表键打开失败(比如权限不足) VirtualFree(path, 0, MEM_RELEASE); return; } DWORD dataSize = (wcslen(path) + 1) * sizeof(WCHAR); LSTATUS return_value = RegSetValueExW(key, RandName(), 0, REG_SZ, (BYTE*)path, dataSize); RegCloseKey(key); VirtualFree(path, 0, MEM_RELEASE);
内容的提问来源于stack exchange,提问作者Azaryab
相关产品推荐
相关产品推荐

