精华内容
下载资源
问答
  • 如果你仔细阅读 MSDN 上关于注册表重定向和访问权限等资料,会发现微软提供了两个特殊的注册表权限位:KEY_WOW64_32KEY、KEY_WOW64_64KEY,来控制访问权限。当使用 RegOpenKeyEx 或 RegCreateKeyEx 访问注册表的时候...

    Window 系统错误代码 ERROR_SUCCESS,本博客中一律使用 NO_ERROR 代替。虽然 ERROR_SUCCESS 与 NO_ERROR 是完全等价的,都代表成功,但是后者却和其他错误代码一样,使用 ERROR 前缀,容易让人误认为是错误代码。而 NO_ERROR 意义很明显,就是无错误。还有另外一个宏 NOERROR 也表示成功,但是使用较少。Windows 系统错误代码的数据类型,其类型微软并没有具体说明。来自 advapi32.dll 中的注册表操作函数多使用 LONG 作为返回值,而来自 shlwapi.dll 中的注册表操作包装函数使用 LSTATUS 作为返回值。为保持统一,本博客统一使用 DWORD 作为 Windows 错误代码数据类型,这是因为 GetLastError 的返回值类型是 DWORD。

    作为 Windows 开发人员,注册表是必须要了解的,读写注册表也是很平常的事情。然而,现实中也发现好多程序员对注册表的有些细节并不了解,尤其是在 64 位系统上重定向,以及 NT 6.0 开始推出的注册表虚拟化。

    MSDN 上的说法是:注册表虚拟化是一种应用程序兼容技术,让那些可能带来全局影响的注册表写入操作重定向到每个用户的位置。这个读取或者写入重定向对于程序而言都是透明的。该技术从 Windows Vista 开始支持。(原文:Registry virtualization is an application compatibility technology that enables registry write operations that have global impact to be redirected to per-user locations. This redirection is transparent to applications reading from or writing to the registry. It is supported starting with Windows Vista.)

    看的出来微软推出这个技术的目的。准确的来说就是,因为向 HKEY_LOCAL_MACHINE(以下简称 HKLM)写入注册表,是会影响到电脑上的所有用户,为了避免这种全局的影响,微软针对其写入操作进行了重定向。究其根本原因,就是 Windows XP 上并没有 UAC,任何程序都可以随意写入 HKLM。然而,从 Windows Vista 开始引入 UAC 之后,微软当然不允许低权限程序来随意操作 HKLM 了,但这样的话又可能会权限问题写入失败,就有可能导致程序运行出错,所以,为了早期的程序能正常运行且不影响现有注册表,微软引入了这个技术,以保证老的程序不会因为权限问题导致注册表写入失败。那么如何避免重定向呢?微软说要嵌入 manifest 并指定应用程序的执行权限,否则程序的注册表读写操作将注册表虚拟化技术重定向到其他位置。manifest 文件在 Visual Studio 中被称为清单文件。关于清单文件,将在其他文章进行讨论,在此我们这里只讨论执行权限级别设置,即 requestedExecutionLevel 这个节点。

    1

    2

    3

    4

    5

    6

    7

    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

        <security>

            <requestedPrivileges>

                <requestedExecutionLevel level="asInvoker" uiAccess="false" />

            </requestedPrivileges>

        </security>

    </trustInfo>

    其中 level 属性值 asInvoker,还可以是 highestAvailable 或 requireAdministrator。意义如下:

    • asInvoker
      以和调用该程序的进程同样的权限级别执行。也可以在右键菜单中选择使用管理员权限执行,但程序不会主动请求管理员权限,即便当前用户具备以管理员执行的条件。
    • highestAvailable
      以当前用户可以获得的最高权限来执行。即当前用户具备以管理员执行的条件时,会请求管理员权限,这种情况下和 requireAdministrator 一样。如果当前用户不具备管理员权限,则类似于 asInvoker 的情况。
    • requireAdministrator
      始终请求管理员权限。如果当前用户不具备管理员权限,则程序无法执行。

    如果程序并没有嵌入清单文件,或者嵌入的清单文件并没有指定执行权限,那么程序的注册表写入将会被重定向,而不是返回失败。如下面的代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    BOOL WINAPI RegWriteStringTest(void)

    {

        BOOL bResult = FALSE;

        HKEY hKey = NULL;

        DWORD dwError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\TestKey"), 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL);

        if (dwError == NO_ERROR)

        {

            TCHAR szValue[] = _T("TestValue");

            TCHAR szData[] = _T("TestData");

            DWORD dwSize = lstrlen(szData) * sizeof(TCHAR) + sizeof(TCHAR);

            dwError = RegSetValueEx(hKey, szValue, 0, REG_SZ, (BYTE *)szData, dwSize);

            if (dwError == NO_ERROR)

            {

                bResult = TRUE;

            }

            RegCloseKey(hKey);

        }

        return bResult;

    }

    在程序未嵌入清单文件或者其中不包含权限信息时,且程序未以管理员权限执行的情况下,期望的返回值是 ERROR_ACCESS_DENIED,实际的返回值却是 NO_ERROR,调用 RegSetValueEx 也同样会成功。然而,打开注册表编辑器在 HKLM\SOFTWARE\TestKey 下查看,却发现并没有写入任何信息。使用 RegSnap 建立执行前后两个注册表快照,对比之后发现,注册表的写入被重定向到:

    1

    HKEY_USERS\<User_SID>_Classes\VirtualStore\MACHINE\SOFTWARE\TestKey

    其中 <User_SID> 为当前用户的 SID 字符串,在本机甚至整个互联网都是唯一的。不同的系统或不同的用户,该 SID 字符串通常都不相同。当读取的时候,也是从上述位置读取,因此实际上也返回成功。就会造成一种假象:注册表系列 API 有 BUG,明明没有写入任何值,结果却返回成功,而且看似根本没写进去的值还能再次读取成功。

    关于注册表虚拟化的更多信息,请访问:
    https://msdn.microsoft.com/en-us/library/aa965884.aspx

    在 64 位系统上,32 位程序读写部分注册表路径时,会被系统所重定向,这有些类似于读写 System32 文件夹的处理方式。比如,写入 HKLM\Software\TestKey,却发现实际写入到 HKLM\Software\Wow6432Node\TestKey,读取亦是如此。现实中发现,很多的程序员在检测一个程序在 HKLM 键下面的注册表信息,通常会针对 HKLM\Software 和 HKLM\Software\Wow6432Node 分别检查,实际上这样检查毫无效果。对于 32 位程序而言,访问 HKLM\Software 时,系统底层会重定向到 HKLM\Software\Wow6432Node,并不能得到真正的 HKLM\Software 下面的信息,即便再访问一次 HKLM\Software\Wow6432Node,和直接访问 HKLM\Software 并没有任何区别。如果你仔细阅读 MSDN 上关于注册表重定向和访问权限等资料,会发现微软提供了两个特殊的注册表权限位:KEY_WOW64_32KEY、KEY_WOW64_64KEY,来控制访问权限。当使用 RegOpenKeyEx 或 RegCreateKeyEx 访问注册表的时候,不需要在子键路径中显式的指定 Wow6432Node,而是应当通过其权限位,如 KEY_READ,和上述二者之一进行组合来控制具体的访问位置。如检测 32 位和 64 位注册表 HKLM\SOFTWARE\TestKey 是否存在 TestValue,正确的代码如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    BOOL WINAPI RegCheckValueTest(void)

    {

        BOOL bResult = FALSE;

        DWORD dwWowFlags[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY };

        DWORD dwWowCount = ARRAYSIZE(dwWowFlags);

        for (size_t i = 0; i < dwWowCount; i++)

        {

            HKEY hKey = NULL;

            DWORD dwAccess = KEY_READ | dwWowFlags[i];

            DWORD dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\TestKey"), dwAccess, &hKey);

            if (dwError == NO_ERROR)

            {

                dwError = RegQueryValueEx(hkeySub, _T("TestValue"), NULL, NULL, NULL, NULL);

                if (dwError == NO_ERROR)

                {

                    bResult = TRUE;

                }

                RegCloseKey(hKey);

            }

        }

        return bResult;

    }

    在 64 位系统上,32 位和 64 位程序分别使用不同的权限位组合访问 HKLM\Software 时,系统底层实际访问的注册表位置对比:

     不包含 KEY_WOW64_***包含 KEY_WOW64_32KEY包含 KEY_WOW64_64KEY
    32 位程序HKLM\Software\Wow6432NodeHKLM\Software\Wow6432NodeHKLM\Software
    64 位程序HKLM\SoftwareHKLM\Software\Wow6432NodeHKLM\Software

    即:32 位程序访问注册表 HKLM\Software 路径时,默认会被系统重定向到 HKLM\Software\Wow6432Node,而在权限位显式指定 KEY_WOW64_64KEY 时则访问 HKLM\Software;64 位程序访问注册表 HKLM\Software 路径时,默认会被系统会访问 HKLM\Software,而在权限位显式指定 KEY_WOW64_32KEY 时则访问 HKLM\Software\Wow6432Node。当然,前提是程序并没有受到注册表虚拟化影响,否则会被写入到以下注册表位置:

    1

    2

    HKEY_USERS\<User_SID>_Classes\VirtualStore\MACHINE\SOFTWARE

    HKEY_USERS\<User_SID>_Classes\VirtualStore\MACHINE\SOFTWARE\Wow6432Node

    而由于注册表的 HKCR 又来自于 HKCU\Software\Classes 和 HKLM\Software\Classes(也包括 64 位系统上的 32 位注册表 HKLM\Software\Wow6432Node\Classes)。故,理论上,上面的键值也可以写成:

    1

    2

    HKEY_USERS\<User_SID>\SOFTWARE\Classes\VirtualStore\MACHINE\SOFTWARE

    HKEY_USERS\<User_SID>\SOFTWARE\Wow6432Node\Classes\VirtualStore\MACHINE\SOFTWARE

    理论如此,不过实际观察发现在 HKCU\SOFTWARE\Wow6432Node 下面只有极少量的注册表信息,而 HKCU 又映射自 HKEY_USERS\<User_SID>,同时 HKEY_USERS\<User_SID>\SOFTWARE\Wow6432Node 下面也只有极少量的注册表信息,没有 Classes 子健,因此 HKCU\SOFTWARE\Wow6432Node 下面(包括其他从此处映射的键)的注册表键通常可以忽略。这说明,注册表针对 32 和 64 位的重定向仅针对 HKLM(包括其他从此处映射的键)有效,如果要访问 HKCU 下面的节点,通常无需考虑重定向的问题。由于 HKEY_USERS\<User_SID> 这个键路径包含了用户 SID,不同用户甚至都不一样,直接用 RegOpenKeyEx 来操作显然是办不到的。微软提供了另外一个函数 RegOpenCurrentUser,来操作当前执行程序用户权限的注册表。通常用户都是使用都是当前登录用户权限启动注册表编辑器,那么其中的 HKCU 也是当前登录用户的注册表。例如,当前登录用户为非管理员账户,但程序使用管理员权限启动,则该程序使用 RegOpenCurrentUser 访问的是管理员的注册表,这和通过管理员权限直接启动注册表编辑器是一样的。示例代码如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    BOOL WINAPI RegCreateClassesKeyTest(void)

    {

        BOOL bResult = FALSE;

        HKEY hKey = NULL;

        REGSAM dwAccess = KEY_READ | KEY_WRITE;

        DWORD dwError = RegOpenCurrentUser(dwAccess, &hKey);

        if (dwError == NO_ERROR)

        {

            HKEY hkeySub = NULL;

            dwError = RegCreateKeyEx(hKey, _T("TestKey"), 0, NULL, 0, dwAccess, NULL, &hkeySub, NULL);

            if (dwError == NO_ERROR)

            {

                RegCloseKey(hkeySub);

                bResult = TRUE;

            }

            RegCloseKey(hKey);

        }

        return bResult;

    }

    在 32 位系统上,不存在这些问题。

    转载:https://www.cnblogs.com/jiake/articles/4956218.html

    展开全文
  • 注册表重定向

    2020-05-08 15:39:13
    HKEY_LOCAL_MACHINE/Software/WOW6432node

    HKEY_LOCAL_MACHINE/Software/WOW6432node

    展开全文
  • Windows系统中两类文件与注册表重定向说明
  • INNOSETUP 操作注册表 重定向至Wow6432Node问题 实际上问题就出在Win64上。Windows 32bit和64bit版本的注册表稍微有不同。我们知道64bit系统上照样可以跑32bit的程序,因此在注册表上也有区分,特意为32bit程序...

    INNOSETUP 操作注册表 重定向至Wow6432Node问题

    实际上问题就出在Win64上。Windows 32bit和64bit版本的注册表稍微有不同。我们知道64bit系统上照样可以跑32bit的程序,因此在注册表上也有区分,特意为32bit程序作了兼容处理。32bit程序对注册表HKEY_LOCAL_MACHINE根下的项目操作都进行了重定向:读取HKEY_LOCAL_MACHINE\SOFTWARE下的键值都会重定向到HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\<company>\<product>。那么这就很好解释了,Premiere Pro目前只能运行在64Bit系统上,因此在Wow6432Node下是不会存在记录的,读取相应键值自然会失败。
    复制代码
    function GetInstallString(): String;
    var
      sInstallPath: String;
    begin
      sInstallPath := 'C:\Program Files\Adobe\Common\Plug-ins\7.0\MediaCore';
      if RegValueExists(HKLM64, 'SOFTWARE\Adobe\Premiere Pro\CurrentVersion', 'Plug-InsDir') then
      begin
        RegQueryStringValue(HKLM64, 'SOFTWARE\Adobe\Premiere Pro\CurrentVersion', 'Plug-InsDir', sInstallPath)
      end
      Result := sInstallPath;
    end;
    复制代码

          通过HKLM32和HKLM64明确指出读取的具体位置,就可以避免上述这种问题了。事实上,在inno setup的说明文档中还有另外一种方法可以尝试,也可以避免64bit系统产生的问题。具体代码:

    复制代码
    var
      OldState: Boolean;
      ResultCode: Integer;
    begin
      // First verify that the user is running a supported 64-bit version
      // of Windows, because calling EnableFsRedirection(False) will
      // raise an exception otherwise.
      if IsWin64 then
      begin
        // Turn off redirection, so that cmd.exe from the 64-bit System
        // directory is launched.
        OldState := EnableFsRedirection(False);
        try
          Exec(ExpandConstant('{cmd}'), '', '', SW_SHOW,
            ewWaitUntilTerminated, ResultCode);
        finally
          // Restore the previous redirection state.
          EnableFsRedirection(OldState);
        end;
      end;
    end;
    复制代码

          关键就是通过调用EnableFsRedirection()函数来禁用注册表操作转发行为。在调用之前先判断当前安装程序是否是运行在64位系统上。

    Update 2016-3-7:

          在64Bit系统上,将动态库文件拷贝到C:\WINDOWS\System32目录下时,会自动重定向到SysWOW64目录下,导致程序运行异常。这事可以通过设置在[Files]段设置Flags:64即可禁用目录重定向(参考链接)。

    参考:https://www.cnblogs.com/csuftzzk/p/innosetup_read_registry.html

    展开全文
  • 使用Wow64DisableWow64FsRedirection 函数可禁用文件系统重定向. 默认情况下系统是启用文件系统重定向的。 使用此函数需要注意下面事项(以下来自MSDN的翻译): 此函数适用于64位系统中32位程序需要访问本机 ...

    使用Wow64DisableWow64FsRedirection 函数可禁用文件系统重定向. 默认情况下系统是启用文件系统重定向的。

    使用此函数需要注意下面事项(以下来自MSDN的翻译):

    此函数适用于64位系统中32位程序需要访问本机 system32 文件夹. 默认情况下, WOW64 文件系统重定向是启用的.

    Wow64DisableWow64FsRedirection 和 Wow64RevertWow64FsRedirection 函数结合使用可以代替 Wow64EnableWow64FsRedirection 函数.

    需要还原文件系统重定向, 调用 Wow64RevertWow64FsRedirection 函数. 每当成功调用 Wow64DisableWow64FsRedirection 函数后必须结合调用 Wow64RevertWow64FsRedirection 函数. 这将确保重定向功能重新启用并释放相关的系统资源.

    注意  Wow64DisableWow64FsRedirection 函数会影响所有当前线程执行的文件操作, 当文件系统重定向禁用一段时间后可能会发生意想不到的后果. 例如, 加载的 DLL 依赖于文件系统重定向, 所以禁用文件系统重定向将引起 DLL 加载失败. 并且, 一些使用延迟加载实现的功能当重定向被禁用时会失败. 初始化延迟加载时失败, 任何使用延迟加载的函数将会失败, 即使重新开启文件系统重定向. 为了避免这些问题, 禁用文件系统重定向之前调用特定的文件输入输出函数(例如 CreateFile)不能被重定向, 并且重新启动文件系统重定向之后需立即使用 Wow64RevertWow64FsRedirection.

    禁用文件系统重定向只影响当前线程的操作. 一些函数, 例如 CreateProcessAsUser, 他们在另一个线程运作, 而不受调用禁用文件系统重定向线程的影响.

    展开全文
  • x64下文件重定向默认是开启的,文件的重定向,需要了解三个API:  Wow64EnableWow64FsRedirection  Wow64DisableWow64FsRedirection  Wow64RevertWow64FsRedirection  不过MSDN说了Wow64EnableWow64...
  • 注册表重定向器通过在WOW64上提供注册表某些部分的单独逻辑视图来隔离32位和64位应用程序。注册表重定向器拦截对其各自逻辑注册表视图的32位和64位注册表调用,并将它们映射到相应的物理注册表位置。重定向过程对...
  • 注册表重定向 zz

    千次阅读 2012-02-09 17:39:50
    无论是Windows XP Professional X64 Edition、Windows Server 2003X64 Edition还是Windows Vista X64 Edition(以下把均统称为X64系统),都引入了一项技术:文件和注册表重定向。  //z 2012-2-9 17:40:1
  • 文件和注册表重定向解决方法

    千次阅读 2016-10-24 09:33:38
    注册表重定向解决办法:转载http://www.2cto.com/os/201411/350858.html 32位程序如何访问64位的注册表(HKLM/Software) 在调用函数RegCreateKeyEx创建注册表项时,对其第六个参数REGSAM samDesired设置中添加...
  • 在 64 位系统上,32 位程序读写部分注册表路径时会被系统重定向,这有些类似于读写 System32 文件夹的处理方式。比如,写入 HKLM\Software\KeyName,却发现实际写入到 HKLM\Software\Wow6432Node\KeyName,读取亦是...
  • 参考资料 微软注册表英文文档 StackOverflow社区回答 1、注册表位置 ...在64bit系统下,通过regedit中查看到指定路径下的注册表项均为64位注册表项,而32位注册表项被重定位到:HKEY_LOCAL_M...
  • *c#在64位上编写32位程序时注册表重定向的问题解决办法*
  • 由于项目需要,在公司接触了powershell和robot framework, 因为robot framework是python编写的,最近将robot framework中的python脚本升级到了3.7,但是在python中运行powershell.exe 时出现了windows注册表项找不...
  • 注册表重定向解决办法: 32位程序如何访问64位的注册表(HKLM/Software) Ø 在调用函数RegCreateKeyEx创建注册表项时,对其第六个参数REGSAM samDesired设置中添加参数KEY_WOW64_64KEY,这样可以实现对64位...
  • 我们知道,X64系统引入了一项技术叫文件和注册表重定向。 之所以有这个技术,是为了将32位程序和64位程序分离开。这种在64位平台上运行32位程序的模拟器被称为WOW64。WOW64是"Windows 32 on Windows 64"的简称,...
  •  x64下文件的重定向依然是WOW64具体执行细节的一部分,跟注册表重定向一样同样是为了将32为程序和64位程序分开。所谓文件重定向通俗点讲就是你去访问某些文件夹的文件的时候,会被定位到其他文件夹下面的文件去,...
  • 应该用什么驱动框架来做,ring0 还是ring3?hook哪几个api呢

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,827
精华内容 5,530
关键字:

注册表重定向