博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
写一个Windows上的守护进程(5)文件系统重定向
阅读量:4550 次
发布时间:2019-06-08

本文共 3306 字,大约阅读时间需要 11 分钟。

写一个Windows上的守护进程(5)文件系统重定向

在Windows上经常操作文件或注册表的同学可能知道,有“文件系统/注册表重定向”这么一回事。大致来说就是32位程序在64位的Windows上运行时,操作系统会把对System32文件夹的访问重定向到SysWow64下,把对HKEY_LOCAL_MACHINE\SOFTWARE的访问重定向到HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node下。当然不止这些路径和注册表。详情请查看MSDN: 和 。

我们通常为了方便发布,都只会编译一份32位的程序,不会编译64的程序。如果代码中涉及到了访问文件和注册表,那就要考虑这个问题了。

Windows提供了两个API(准确的说是3个,但其中一个已不推荐使用了)来禁用文件系统/注册表重定向:Wow64DisableWow64FsRedirection,Wow64RevertWow64FsRedirection。顾名思义,前者用于禁用,后者用于恢复。

有的同学可能就说了:我一直禁用就行了,干嘛还要恢复?这你就想少了,有的代码段可能并不关心是否有重定向,所以并没有考虑这个问题,假若这个代码段的结果会影响多个线程,而你刚好又把包含这个代码段的某一线程的重定向禁用了,那就成了有的线程禁用了重定向,有的线程没有禁用,获取的结果就不一致了。

一般我们在会有重定向问题的函数调用前禁用重定向,调用完毕后,恢复重定向。这很容易让人想到使用RAII手法:在类构造函数中禁用,析构函数中恢复:

class scoped_disable_wow64_fsredirection : public boost::noncopyable{public:    scoped_disable_wow64_fsredirection();    ~scoped_disable_wow64_fsredirection();private:    static bool disable(void **ppOldValue);    static bool revert(void *pOldValue);private:    void *_pOldValue;};

构造函数的实现中调用了disable,析构函数的实现中调用了revert。

其中disable就是调用了Wow64DisableWow64FsRedirection,revert就是调用了Wow64RevertWow64FsRedirection。

注:类名字这么长是为了能够达到“顾名思义”的程度。还没想到什么更好的名字。哎,起名真是个头疼的事。

但是我们不能直接调用这两个Windows API,为什么呢?

在WindowsXP这么流行的平台上,它们没有啊!你要是直接调用这两个函数,在XP上,整个程序就跑不起来。

怎么办?

用GetProcAddress动态加载这两个函数,如果没有这两个函数,就说明不存在重定向问题。

以下是实现:

static boost::once_flag once_ = BOOST_ONCE_INIT;typedef int (__stdcall *fnWow64DisableWow64FsRedirection)(void *);typedef int (__stdcall *fnWow64RevertWow64FsRedirection)(void *);static fnWow64DisableWow64FsRedirection g_fnWow64DisableWow64FsRedirection = NULL;static fnWow64RevertWow64FsRedirection g_fnWow64RevertWow64FsRedirection = NULL;static void load_wow64_funcs(){    g_fnWow64DisableWow64FsRedirection = reinterpret_cast
(WindowsUtil::load_function("Kernel32.dll", "Wow64DisableWow64FsRedirection")); g_fnWow64RevertWow64FsRedirection = reinterpret_cast
(WindowsUtil::load_function("Kernel32.dll", "Wow64RevertWow64FsRedirection"));}scoped_disable_wow64_fsredirection::scoped_disable_wow64_fsredirection() : _pOldValue(NULL){ boost::call_once(once_, load_wow64_funcs); disable(&_pOldValue);}scoped_disable_wow64_fsredirection::~scoped_disable_wow64_fsredirection(){ revert(_pOldValue);}bool scoped_disable_wow64_fsredirection::disable(void **ppOldValue){ bool ret = true; if (g_fnWow64DisableWow64FsRedirection) { if (!g_fnWow64DisableWow64FsRedirection(ppOldValue)) { ErrorLogLastErr("Wow64DisableWow64FsRedirection fail"); ret = false; } } return ret;}bool scoped_disable_wow64_fsredirection::revert(void *pOldValue){ bool ret = true; if (g_fnWow64RevertWow64FsRedirection) { if (!g_fnWow64RevertWow64FsRedirection(pOldValue)) { ErrorLogLastErr("Wow64RevertWow64FsRedirection fail"); ret = false; } } return ret;}

这里用了前面文章讲到的call_once去加载这两个函数。

load_function封装了GetModuleHandleA- GetProcAddress两个函数的调用,详情请参看源码。

 

使用时,仅需定义一个类实例就可以了。切记,要尽量缩小作用域,以免影响其他代码段。

 

源码: (主)&& (提升逼格用的)。

 

2015年11月1日星期日

 

**********************************************************************

更新记录:

【2015年11月6日 星期五】set boost::once_flag instance init value to BOOST_ONCE_INIT

**********************************************************************

转载于:https://www.cnblogs.com/mkdym/p/4928535.html

你可能感兴趣的文章
jQuery.Data源码
查看>>
将博客搬至CSDN
查看>>
layui问题之模拟select点击事件
查看>>
ckplayer-超酷网页视频播放器的使用
查看>>
35+多用途WordPress主题
查看>>
KVO实现原理
查看>>
a:link,a:visited,a:hover,a:active
查看>>
DTD与XML的关系
查看>>
ASP.NET Development Server使用方法
查看>>
服务器运维基础指南
查看>>
读后感
查看>>
使用Crypto对数据进行加密解密
查看>>
CSS五類常用選擇器(收藏)
查看>>
have a thing用法
查看>>
为什么 远程钩子 必须使用动态链接库dll(而且是.data? 段共享的动态链接库)...
查看>>
redis 从0到1 linux下的安装使用 数据类型 以及操作指令 一
查看>>
MongoDB-启动的时候出现了问题
查看>>
解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误
查看>>
第三次作
查看>>
模板 - ST表
查看>>