如果要保存的密钥是HKEY_LOCAL_MACHINE,为什么RegSaveKey()失败并显示错误代码5(访问被拒绝)?

时间:2018-05-28 19:40:52

标签: c windows winapi

此问题与所使用的编程语言无关。

在Windows 7 SP1和Windows 10版本1803中测试。

Symptomps

如果要保存的密钥为HKEY_LOCAL_MACHINE

RegSaveKey()会失败并显示错误代码5(访问被拒绝)。

如果指定了子键,则不会发生此错误,例如HKEY_LOCAL_MACHINE\SYSTEM

如果密钥为HKEY_CURRENT_USER,则也不会发生此错误。

第一个样本

在这里,我使用AutoIt快速编写重现错误的a sample code。我还将示例代码编译为.EXE,以便人们轻松查看问题。

第二个样本

REG.EXE ,这是一个内置的Windows工具使用Visual C ++编写(标签包含C的原因)具有完全相同的如上所述的问题。这并不奇怪,因为根据我的调查,REG.EXE SAVE命令实际上使用了未记录的 NtSaveKey()。顺便说一句, RegSaveKey()在内部调用 NtSaveKey()

REG.EXE SAVE "HKLM" "HKLM.hiv" /Y

上述命令失败并显示错误"访问被拒绝"。请注意,我将命令作为 Administrator 运行。

问题

此错误的原因是什么?有没有办法让 RegSaveKey()适用于HKEY_LOCAL_MACHINE(不指定子项)?

更新

我的进一步测试显示 regedit.exe 与上述问题相同。

  • HKEY_LOCAL_MACHINE导出到.HIV文件失败;但是,将其导出到.REG文件会成功。
  • HKEY_LOCAL_MACHINE\<subkey>导出到.HIV文件成功。
  • HKEY_CURRENT_USER导出到.HIV文件成功。
  • HKEY_CURRENT_USER\<subkey>导出到.HIV文件成功。

1 个答案:

答案 0 :(得分:4)

保存注册表项的所有API在内部调用CmSaveKey。在此函数的源代码中,我们在开头看到以下block of code

    //
    // Disallow attempts to "save" the master hive
    //
    Hive = KeyControlBlock->KeyHive;

    if (Hive == &CmpMasterHive->Hive) {
        return STATUS_ACCESS_DENIED;
    }

HKEY_LOCAL_MACHINE(即“\ Registry \ Machine”)位于主配置单元中,因此CmSaveKey会向调用者返回STATUS_ACCESS_DENIED(0xc0000022)。 Windows子系统将此状态代码转换为ERROR_ACCESS_DENIED(5)。