windows注册表重定向问题

c++

Posted by YiMiTuMi on April 17, 2019

windows注册表重定向问题

通过windows函数SHGetValueW打开注册表的指定路径并查找相对用的Value时,函数返回错误代码 = 2(系统找不到指定的文件),这就牵扯出了关于windows注册表重定向的问题。

为什么会有重定向这个问题呢,是为了将32位程序和64位程序分离开。在64位平台上运行32位程序的模拟器被称为WOW64。WOW64是”Windows 32 on Windows 64”的简称,它在系统层中另提供了一层,以支持老式的32位程序。所以说32位的程序和64位的程序就被分开存放了。

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall

这是64位程序存放的路径,但是当用SHGetValueW函数调用时,因为重定向问题系统会自动将路径重新定位到下面的32位程序存放的路径中。

HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall

所以就会出现找不到指定文件这一错误。

解决办法

可以调用函数Wow64DisableWow64FsRedirection临时性关闭系统注册表重定向问题,这时系统就能正常的进入64位程序的安装路径中了。但是在使用结束时要用函数Wow64RevertWow64FsRedirection来恢复系统注册表重定向。

用法和常见问题

Wow64DisableWow64FsRedirectionWow64RevertWow64FsRedirection函数明确说明了只能在xp64位以上的系统使用。

使用方法:

Wow64DisableWow64FsRedirection(0); //禁用重定向
...
....
....
Wow64RevertWow64FsRedirection(0); //恢复重定向

但是在使用时我们经常会遇到这种情况,写的程序需要重定向,但是要兼容所有系统,比如xp32位,如果现在不仅以操作就会出现在xp32中运行 连接不到当前函数的问题,即使你没有去调用这个函数。因为他会在你运行的时候将需要的DLL和函数添加进去(解释的不是很合理,《程序员自我修养》上有说, 忘得差不多了)。所以我们要在调用前判断当前函数是否支持当前操作系统,也就是说是否在DLL里有这个函数,有则链接添加,没有就跳过。

声明

WINBASEAPI
BOOL
WINAPI
Wow64DisableWow64FsRedirection (__out PVOID *OldValue);

WINBASEAPI
BOOL
WINAPI
Wow64RevertWow64FsRedirection ( __in PVOID OlValue);


BOOL Is64BitOs()
{
	static BOOL isWow64 = FALSE;
	static BOOL valid = FALSE;
	typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process);
	LPFN_ISWOW64PROCESS fnIsWow64Process;
#ifdef _WIN64
	return TRUE;
#endif
	if (valid)
		return isWow64;

	fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandleA("kernel32"), "IsWow64Process");

	if (fnIsWow64Process != NULL)
		if (!fnIsWow64Process (GetCurrentProcess(), &isWow64))
			isWow64 = FALSE;

	valid = TRUE;
	return isWow64;
}

使用:

PVOID OldValue; 
HINSTANCE hlibrary; 
typedef int (__stdcall * Wow64DisableWow64FsRedirection)(LPVOID); 
typedef int (__stdcall * Wow64RevertWow64FsRedirection)(LPVOID); 
Wow64DisableWow64FsRedirection f_Wow64DisableWow64FsRedirection = NULL; 
Wow64RevertWow64FsRedirection f_Wow64RevertWow64FsRedirection = NULL; 
//链接当前DLL,因为函数在当前DLL中
hlibrary = LoadLibrary(_T("Kernel32.dll"));
//在当前DLL中遍历调用的函数
f_Wow64DisableWow64FsRedirection = (Wow64DisableWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64DisableWow64FsRedirection")); 

if (f_Wow64DisableWow64FsRedirection  && (Is64BitOs()))
   {
      //但前函数存在
      f_Wow64DisableWow64FsRedirection(&OldValue);
      //禁用重定向
      f_Wow64RevertWow64FsRedirection = (Wow64RevertWow64FsRedirection) GetProcAddress(hlibrary, ("Wow64RevertWow64FsRedirection")); 
      ////////////////////////////
	...
	...
	...
	...
      ////////////////////////////
      //恢复重定向
     if(f_Wow64RevertWow64FsRedirection)
       {
          f_Wow64RevertWow64FsRedirection (OldValue);
       } 
    }

薰衣草 – 等待爱情