Winapi 64位进程如何具有文件系统和注册表的32位视图?

Winapi 64位进程如何具有文件系统和注册表的32位视图?,winapi,64-bit,syswow64,Winapi,64 Bit,Syswow64,为了向后兼容,我的64进程需要查看文件系统和注册表的32位视图 我知道如何使用Wow64DisableWow64FsRedirection和Wow64RevertWow64FsRedirection使32位进程看到文件系统和注册表的64位视图 但是如何使64位进程具有文件系统和注册表的32位视图?您需要显式地查看WOW64项/目录。实际上没有64位注册表,只有注册表,而Wow64重定向只是将32位进程重定向到不同的子项。因此,当一个32位进程请求HKLM\Software\foo时,注册表API

为了向后兼容,我的64进程需要查看文件系统和注册表的32位视图

我知道如何使用Wow64DisableWow64FsRedirection和Wow64RevertWow64FsRedirection使32位进程看到文件系统和注册表的64位视图


但是如何使64位进程具有文件系统和注册表的32位视图?

您需要显式地查看WOW64项/目录。实际上没有64位注册表,只有注册表,而Wow64重定向只是将32位进程重定向到不同的子项。因此,当一个32位进程请求HKLM\Software\foo时,注册表API实际上会说,等等,您是32位的,所以我要假装您请求的是“HKLM\Software\Wow6432Node\foo”

因此,考虑到这一点,没有办法在32位注册表中查看64位进程,因为没有32位注册表。相反,您只需执行Wow64重定向逻辑自动执行的操作

编辑

对于注册表,实际上有一个可以在中指定的键


对于文件系统,您可以尝试一下,但我不确定它是否能工作…

如果您想查看32位注册表,可以使用所述的键\u WOW64\u 32KEY


如果要访问SysWOW64目录,可以使用getsystemwow64目录,如所述

KEY\u WOW64\u 32KEY适用于64位和32位进程

从实验中可以看出,Wow64EnableWow64FsRedirection/Wow64DisableWow64FsRedirection似乎在64位进程中不起作用,而其名称表明它似乎只在WOW64进程中起作用

因此,为了从64位进程获得文件系统的32位视图,需要更改路径以指向正确的位置

这真的很难看,但是这里有一个C++代码示例,它是如何根据文件系统重定向来执行的。需要加强

#include"boost/filesystem.hpp"
#include"wstring"
#include"shfolder.h"
#include"Shlobj.h"
bool redirectPathRoot( boost::filesystem::wpath pathFromRoot, boost::filesystem::wpath pathToRoot, boost::filesystem::wpath & pathToRedirect )
{
bool bPathWasRedirected = false;
boost::filesystem::wpath theNewPath;
boost::filesystem::wpath::iterator iPathToRedirect = pathToRedirect.begin();
boost::filesystem::wpath::iterator iFromRoot = pathFromRoot.begin();
bool bMatch = true;
while( iPathToRedirect != pathToRedirect.end() && iFromRoot != pathFromRoot.end() && bMatch )
{
    //
    // see if the root of the path we are checking matches 
    //
    bMatch = ( std::wstring(*iPathToRedirect++) == std::wstring(*iFromRoot++) );
}
if( bMatch && iFromRoot == pathFromRoot.end() )
{
    theNewPath = pathToRoot;
    //
    // these guys need to be redirected
    //
    while( iPathToRedirect != pathToRedirect.end() )
    {
        theNewPath /= *iPathToRedirect++;
    }
    bPathWasRedirected = true;
    pathToRedirect = theNewPath;
}
return bPathWasRedirected;
}
std::wstring adjustPathFor32BitOn64BitProcess( LPCWSTR thePath )
{
std::wstring strPath(thePath);
boost::to_lower(strPath);
//
// default to the original path
//
boost::filesystem::wpath theNewPath(strPath.c_str());
theNewPath.normalize();
//
// init the supplied path
//
boost::filesystem::wpath pathToCheck( strPath.c_str() );
pathToCheck.normalize();
//
// get the path for the 32 bit folder on a 64 bit system
//
wchar_t strTemp[MAX_PATH] = L"\0";
GetSystemWow64Directory( strTemp, MAX_PATH );
std::wstring strSysWow64 = strTemp;
boost::to_lower( strSysWow64 );
boost::filesystem::wpath pathSysWow64( strSysWow64.c_str() );
pathSysWow64.normalize();

//
// get the path for the system directory
//
GetSystemDirectory( strTemp, MAX_PATH );
std::wstring strSys = strTemp;
boost::to_lower( strSys );
boost::filesystem::wpath pathSys( strSys.c_str() );
pathSys.normalize();

//
// get the path for the Program Files directory
//
SHGetFolderPath( NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_DEFAULT, strTemp);
std::wstring strPrograms = strTemp;
boost::to_lower( strPrograms );
boost::filesystem::wpath pathPrograms( strPrograms.c_str() );
pathPrograms.normalize();

//
// get the path for the Program Files x86 directory
//
SHGetFolderPath( NULL, CSIDL_PROGRAM_FILESX86, NULL, SHGFP_TYPE_DEFAULT, strTemp);
std::wstring strProgramsX86 = strTemp;
boost::to_lower( strProgramsX86 );
boost::filesystem::wpath pathProgramsX86( strProgramsX86.c_str() );
pathProgramsX86.normalize();

//
// get the path for the Windows\lastgood\system32 directory
//
SHGetFolderPath( NULL, CSIDL_WINDOWS, NULL, SHGFP_TYPE_DEFAULT, strTemp);
std::wstring strWindows = strTemp;
boost::to_lower( strWindows );
boost::filesystem::wpath pathWindows( strWindows.c_str() );
pathWindows.normalize();

boost::filesystem::wpath pathWindowsLastGoodSystem32( strWindows.c_str() );
pathWindowsLastGoodSystem32 /= L"lastgood";
pathWindowsLastGoodSystem32 /= L"system32";
pathWindowsLastGoodSystem32.normalize();

boost::filesystem::wpath pathWindowsLastGoodSysWOW64( strWindows.c_str() );
pathWindowsLastGoodSysWOW64 /= L"lastgood";
pathWindowsLastGoodSysWOW64 /= L"syswow64";
pathWindowsLastGoodSysWOW64.normalize();


//
// finally, regedit...
//
boost::filesystem::wpath pathRegedit( strWindows.c_str() );
pathRegedit /= L"regedit.exe";
pathRegedit.normalize();

boost::filesystem::wpath pathRegeditSysWOW64( pathSysWow64 );
pathRegeditSysWOW64 /= L"regedit.exe";
pathRegeditSysWOW64.normalize();

//
// now see if the supplied path matches system directoy
//
boost::filesystem::wpath::iterator iPathToCheck = pathToCheck.begin();
boost::filesystem::wpath::iterator iSys = pathSys.begin();
bool bMatch = true;
while( iPathToCheck != pathToCheck.end() && iSys != pathSys.end() && bMatch )
{
    //
    // see if the beginning of the path we are checking matches the system path
    //
    bMatch = ( std::wstring(*iPathToCheck++) == std::wstring(*iSys++) );
}
if( bMatch && iSys == pathSys.end() )
{
    //
    // the supplied path matches at least as far as the system dir...
    //
    if( iPathToCheck == pathToCheck.end() )
    {
        //
        // ...actually its an exact match, so redirect it
        //
        theNewPath = pathSysWow64;
    }
    else
    {
        //
        // ...however, there are a few exceptions....
        //
        boost::filesystem::wpath::iterator iTemp = iPathToCheck;
        if( 
                !(
                    std::wstring(*iTemp) == L"drivers" && 
                    ( 
                        (++iTemp) != pathToCheck.end()  && 
                        std::wstring(*(iTemp)) == L"etc" 
                        )
                    ) 
                &&
                (std::wstring(*iPathToCheck) != L"catroot") &&
                (std::wstring(*iPathToCheck) != L"catroot2") &&
                (std::wstring(*iPathToCheck) != L"logfiles") &&
                (std::wstring(*iPathToCheck) != L"spool")
                )
        {
            //
            // all but the above dirs should be redirected
            //
            theNewPath = pathSysWow64;
            while( iPathToCheck != pathToCheck.end() )
            {
                theNewPath /= *iPathToCheck++;
            }
        }
    }
}
else
{
    //
    // didn't match the system dir... see if it matches the Program Files dir
    //
    if(!redirectPathRoot(  pathPrograms, pathProgramsX86, theNewPath ))
    {
        //
        // now try %windir%/lastgood/system32
        //
        if(!redirectPathRoot(  pathWindowsLastGoodSystem32, pathWindowsLastGoodSysWOW64, theNewPath ))
        {
            //
            // finally, regedit
            //
            redirectPathRoot(  pathRegedit, pathRegeditSysWOW64, theNewPath );
        }
    }

}
return theNewPath.file_string();}

派对有点晚了,但是你不能创建一个小的32位进程来完成你的32位工作吗?那么WOW64的所有内在优点都将发挥作用


不确定您的开发语言/运行时是什么样的,因此无法提供关于进程间通信的进一步建议。

urgh!你的意思是手动删除所有注册表路径和文件系统路径。。。我真的希望能有一个API用于此。对于注册表来说,这相当简单,但我非常确定SysWow64目录不一定必须位于windows目录下。感谢链接,KEY_WOW64_32KEY将在32位或64位进程中工作,因此我的问题解决了一半。我不认为Wow64EnableWow64FsRedirection会…@deltanine:是的,不确定文件系统的那个。。。文档中似乎没有这样说。如何在64位机器上转换路径,使其指向32位文件?我确实考虑过这一点,因为我们的应用程序已经使用代理进程执行各种COM操作,以便在64位进程中承载32位COM对象,反之亦然。但是我们使用64位端口的唯一原因是因为客户需要它——实际上,应用程序不需要64位支持。甚至说C++代码重新映射路径是丑陋的,它比COM替代路径更不丑陋。