1. 64bit操作系统的重定向机制以及目的 
   在64bit操作系统中,为了无缝兼容32bit程序的运行,64bit的Windows操作系统采用重定向机制。目的是为了能让32bit程序在 64bit的操作系统不仅能操作关键文件文夹和关键的注册表并且又要避免与64bit程序冲突。
  微软采用重定向机制的原理很简单,说白了就是 让关键文件/文件夹或者关键注册表有2个副本。 1个副本是给32bit程序访问,一个副本给64bit程序访问。
  
   PS: 以上不是用专业术语解释,只是用白话解释。如果觉得不够专业,可以查阅详细资料

2. 64bit操作系统是如何控制32bit和64bit程序访问对应各自的副本? 
   这个问题,就是重定向机制的核心功能。
  
   例子: 32bit程序在64bit Windows操作系统,要访问system32目录。
   在正常的情况下:  64bit Windows操作系统的重定向机制 会在内部  把 system32目录 转向 syswow64目录, 因此32bit程序对system32目录的操作,实际是对syswow64目录进行操作。
   以为由于重定向的干预,因为可以这么认为 system32目录是供给64bit程序使用的,而syswow64目录是给32bit程序使用的
   代码例子: 32bit程序中有一个代码
   deletefile('c:/windows/system32/a.txt') ;
   这个代码在64bit Windows操作系统中,它只会删除syswow64目录中的a.txt文件,而不会删除system32目录的a.txt文件。  这就是重定向的干预结果。

3. 那32bit程序要真正访问64bit程序的system32目录要如何做呢? 
   微软提供一套API,可以做到上面的要求。 通过 Wow64DisableWow64FsRedirection 和 Wow64RevertWow64FsRedirection API 来配合使用

代码例子: 32bit程序中有一个代码
   Wow64DisableWow64FsRedirection  // 关闭重定向
   deletefile('c:/windows/system32/a.txt') ;
   Wow64RevertWow64FsRedirection   // 恢复重定向
   以上代码,就有效的删除了system32目录里面的a.txt文件,而不是syswow64目录中的a.txt文件。

4. 32bit程序在64bit操作系统下不关闭重定向功能,在全盘枚举系统目录时,是否可以同时把32bit和64bit的目录都枚举出来? 
   经过我测试,无法同时枚举出来,只能做2次重复扫描,第一次在打开重定向枚举出32bit的目录,然后第二次关闭重定向,在枚举64bit的目录。

6. 既然文件目录有重定向,那么注册表有没有重定向之后的副本? 
   有, 跟文件重定向一样。
   示例: 32bit程序在64bitWindows操作系统正常访问'HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID' 
   在重定向的干预下,32bit程序被重定向访问到'HKEY_LOCAL_MACHINE/SOFTWARE/Classes/Wow6432node /CLSID'
  
   如果要真正访问'HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID' ,请按照 第3点的 代码示例来做。

7. 32bit程序在64bit操作系统下不关闭重定向功能,枚举系统注册表,是否可以同时把32bit和64bit的注册信息同时枚举出来? 
   经过我测试,无法同时枚举出来,只能做2次重复扫描,第一次在打开重定向枚举出32bit的注册表信息,然后第二次关闭重定向,在枚举64bit的注册表信息。

8. 32bit程序在64bit操作系统下不关闭重定向功能,直接硬编码访问32bit副本的关键目录和关键注册表是否可行?
   经过我测试,是可以的。
   代码例子: 
   deletefile('c:/windows/syswow64/a.txt') ;
   以上代码就是可以直接删除syswow64目录下的a.txt文件.
   同理,注册表访问也一样适用.

1> Delphi程序的TRegistry类无法对KEY_WOW64_64KEY 兼容。也就是说,TRegistry.Create(KEY_WOW64_64KEY or KEY_ALL_ACCESS) 这样是无效的。

2> SHDeleteKey这类Shellapi 对 KEY_WOW64_64KEY 不兼容。也就是说就算你关闭重定位机制,也无法对64bit的注册表操作。一律全部重定位到Wow64xxx 的位置。
    这是因为这类API没有KEY_WOW64_64KEY这个标志为的设置

3> 针对RegDeleteKeyEx这类带有Ex的注册表函数,不管你是否显示关闭和打开重定位机制,只要在参数设置KEY_WOW64_64KEY 或者 KEY_WOW32_32KEY 就可以直接操作 64BIT 或者 32BIT的注册表了。

下面来个代码例子 32bit程序无缝兼容于64bit操作系统, 同时删除32bit和64bit的注册表项HKEY_LOCAL_MACHINE/software/aaaa  [delphi伪代码]

if IsWow64 then
  begin  //  如果是在64bit环境下运行32bit程序
     //  1 关闭从定向
    Wow64DisableWow64FsRedirection
    //  删除64bit的注册表信息  HKEY_LOCAL_MACHINE/software/aaaa 的项,包括子项
    RegOpenKeyEx(HKEY_LOCAL_MACHINE, software/aaaa ,  0, KEY_WOW64_64KEY or KEY_ALL_ACCESS, hkey_Opend) ;
    // 执行删除
    RegDeleteTree(hkey_Opend, nil) ;
    RegDeleteKeyEx(HKEY_LOCAL_MACHINE, software/aaaa, KEY_WOW64_64KEY or KEY_ALL_ACCESS, 0) ; 
    RegCloseKey(hkey_Opend) ;
    // 2 恢复重定向
    Wow64RevertWow64FsRedirection

end ;
  //  下面开始执行32bit的删除
  Reg_Operate := TRegistry.Create() ;
  Reg_Operate.RootKey := HKEY_LOCAL_MACHINE ;
  Reg_Operate.OpenKey('software/aaaa', False) ;
  Reg_Operate.DeleteKey('/software/aaaa') ;
  Reg_Operate.CloseKey() ;

管理员身份运,普通用户,WIN7下读写注册表,WIN7对普通用户可能做了特殊处理,如果读写local_machine的键,会自动跳转到current_user下。

这人遇到这个问题

“http://blog.csdn.net/huzgd/article/details/6314489”

其他:

1.KEY_WOW64_64KEY 和 KEY_WOW64_32KEY

64位的windows系统的注册表分为32 位注册表项和64位注册表项两部分。在64bit系统下,通过regedit中查看到指定路径下的注册表项均为64位注册表项,而32位注册表项被重定位到了WOW6432Node。比如HEKY_CLASSES_ROOT\CLSID是64位的注册表项,而HEKY_CLASES_ROOT\WOW6432Node\CLSID则是32位的。当然,像HEKY_CURRENT_USER下的都是shared项,不区分32位还是64位。具体可以从msdn中查到:http://msdn.microsoft.com/en-us/library/ms724072(v=VS.85).aspx 。

当然微软考虑到了这样的改变对现有软件的影响,因为64位系统上既可以跑64位的程序,也可以跑32位的。比如我在代码中对注册表的读操作::RegOpenKeyExA(HKEY_CLASSES_ROOT, regSubKeyName, 0, KEY_ALL_ACCESS, &hKey),程序是在32位的windows xp系统下用vs2005编译的,放到64位系统上则读的WOW6432Node下的项。如果需要读取64位下的项,则需要显示的指定,即::RegOpenKeyExA(HKEY_CLASSES_ROOT, regSubKeyName, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hKey)。当然这里也可以加上KEY_WOW64_32KEY,这种情况下跟没有指定是一样的。

2. 判断系统是否是64位

调试过程中过了误区,以为需要显示的指定是64位还是32位的注册表项,这样就面临一个问题:怎么判断系统是64位还是32位,在网上找了几种方法,这里也做个总结:

1)通过sizeof(int)或者sizeof(void*)的值是4还是8来判断。

这种属于屁股决定脑袋的方法,但是网上一查还真是有不少人给这样的答案。首先,int类型在64位的机器上也是占4个字节,而且这个完全依赖于编译器的实现,编译器可以用32位也可以用64位来表示整型数据。其次,sizeof操作是编译期间决定的,不是动态获取的,也就是说这个值依赖于你的编译环境,如果是在32位的系统上编译,不管跑到什么系统上去执行程序,总是会返回4.

2)通过宏#if defined(_WIN64)来判断

这个与上面的一样,也是完全依赖于编译环境。

3) 根据GetSystemInfo的结果来判断

通常代码如下

SYSTEM_INFO  si;

GetSystemInfo(&si);

if((si.wProcessorArchitecture & PROCESSOR_ARCHITECTURE_IA64)
|| (si.wProcessorArchitecture & PROCESSOR_ARCHITECTURE_AMD64)

//64 bit;
else
    //32 bit.

本以为这段代码可以work,但是亲自在intel cpu上安装了64位win7的机器上测试不成功,返回值是0,即PROCESSOR_ARCHITECTURE_INTEL

4) 根据环境变量PROCESSOR_ARCHITECTURE来判断
    if(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE").IndexOf("64"))
             //64-bit
    else
             //32-bit
    这个破天荒执行成功了,查了一下64位win7的系统环境变量,该变量值为AMD64。不可思议的是cpu型号是intel(R) Core(TM) i3-2120 cpu @ 3.30GHZ,不知道怎么解释。但是感觉这种方法也不是很靠谱。

试了以上四种方式觉得不靠谱之后就没再查其它方法了。

5) 据说IsWow64可以,没有测试

3. 64位windows系统上写注册表失败
     代码如下:
::RegOpenKeyExA(HKEY_CLASSES_ROOT, regSubKeyName, 0, KEY_ALL_ACCESS, &hKey);
::RegSetValueExA(hKey, "", 0, REG_SZ, (LPBYTE)"test", strlen("test")+1);
    打开注册表项是成功的,而写注册表函数总是返回5,即ERROR_ACCESS_DENIED,首先排除了两个原因,因为用的帐号是管理员,而且打开函数中设置KEY_ALL_ACCESS,包括了写权限。手动打开注册表并修改,是没有任何问题的。隐约觉得是UAC搞得鬼,将其设位最低和最高,都没有起作用。
     最后的解决方法让人吐血,右键单击应用程序图标,选择“以管理员权限”运行,一切ok了。

真是杯具,我为我的哨子付出了太大的代价。

转载于:https://www.cnblogs.com/chenboo/archive/2012/02/29/2373368.html

32bit程序在64bit操作系统下处理重定向细节相关推荐

  1. Win7让你的程序变得更加漂亮,同样的程序在Win7操作系统下的效果对比

    老婆施舍了一台ThinkPad X200, 这也是经手的第3台ThinkPad笔记本电脑了,其他品牌先不算(小太阳一个.方正一个.Dell一个), 最早购买的是R51花了一万三千多大洋,刚购买不到一个 ...

  2. win7+64bit操作系统下搭建android开发环境

    参考: http://blog.csdn.net/badboy1110/article/details/6670414 http://www.cnblogs.com/skynet/archive/20 ...

  3. delphi7的程序在英文系统下显示中文乱码

    关于delphi的程序在英文操作系统下乱码问题 由于delphi7编译的程序是非unicode程序(代码页),所有在英文操作系统下会有乱码的问题. 解决方法: 1. 首先在Lageuage中选&quo ...

  4. Ubuntu16.04(64bit)兼容32bit程序

    Ubuntu16.04(64bit)兼容32bit程序 版权声明:本文为博主原创文章,未经博主允许不得转载. 0 前言 使用Ubuntu16.04(64bit)进行嵌入式开发时,默认情况下无法正常运行 ...

  5. c语言程序能够在不同的操作系统下运行,这说明c语言具有很好的,程序设计(C)作业一(有答案)...

    程序设计(C)作业一 1.C语言程序的执行,总是起始于(). A.程序中的第一条可执行语句 B.程序中的第一个函数 C.main函数 D.包含文件中的第一个函数 2.以下叙述不正确的是(). A.一个 ...

  6. c语言程序能够在不同的操作系统下运行,这说明c语言具有很好的,上海交通大学继续教育学院2012春——程序设计(C)作业1(有答案)...

    程序设计(C)作业一 1. C语言程序的执行,总是起始于( ). A.程序中的第一条可执行语句 B.程序中的第一个函数 C.main函数 D.包含文件中的第一个函数 2. 以下叙述不正确的是( ). ...

  7. 1024程序员节持续引爆星城:500万程序员线上线下互动,共迎开源软件、操作系统新时代...

    10月23日,"长沙 · 中国1024程序员节"在长沙盛大开幕.大会以硬核技术和开源文化为主题,囊括岳麓尖峰对话.2020开源技术英雄大会.20+场热门技术分论坛/峰会,以及&qu ...

  8. linux文件损坏怎么修复工具,在Ubuntu操作系统下修复损坏程序包的三种办法

    如果在 Ubuntu 操作系统下出现损坏的程序包,通常有三种办法可以修复它们,分别是:使用 apt 或 apt-get.使用 dpkg 及解除 dpkg 锁,下面为你一一介绍. 背景 apt 是 Ub ...

  9. linux怎么进win7系统安装程序,Linux操作系统在win7操作系统下怎么安装?

    Linux操作系统在win7操作系统下怎么安装? 更新时间:2019-03-08 17:45 最满意答案 可以装虚拟的了,这样的即安全又实用的,就是先下载一个软件VM和一个Linux的镜像文件就可以了 ...

  10. linux 32bit 改为64bit问题

    32bit-64bit porting work注意事项 64位服务器逐步普及,各条产品线对64位升级的需求也不断加大.在本文中,主要讨论向64位平台移植现有32位代码时,应注意的一些细小问题. 什么 ...

最新文章

  1. 2. 离散特征处理方法--特征交叉 feature crosses
  2. 开启报名丨智源论坛 · 北大教授宋令阳:超材料感知与通信
  3. python官网打不开-python为什么打不开
  4. nginx_gzip压缩提升网站的传输速度
  5. java 唯一id生成算法_分布式全局唯一ID生成方案之snowflake算法
  6. SAP ABAP SE16 and SE17
  7. python脚本式编程_Python编程入门(一)
  8. python 定义字符串变量_Python变量和字符串详解
  9. Android应用性能优化(3)---加快应用启动速度
  10. 在xtragrid中如何自定义日期编辑控件的格式
  11. php5.6源码包,PHP-5.6.8 源码包编译安装
  12. c语言开根函数不用math,c语言开平方函数怎么用 该函数头文件:math.h;
  13. springboot微信小程序 获取微信unionid
  14. 七牛云对象存储实现文件的上传与下载
  15. 加法器verilog
  16. C语言中文网设计模式,C语言和设计模式(访问者模式)
  17. Android 自定义View漫飞舞超炫超浪漫特效
  18. 射击类项目(数据的持久化保存)整理四
  19. 传智播客C语言视频第二季 第一季基础上增加诸多C语言案例讲解,有效下载期为10 5-10 10关闭
  20. Could not transfer artifact XXX 问题处理

热门文章

  1. Java商城秒杀系统的设计与实战视频教程(SpringBoot版)_汇总贴
  2. 阶段3 1.Mybatis_07.Mybatis的连接池及事务_3 mybatis连接池的分类
  3. 封装条形码MaHelper
  4. 【求最大公共子串长度】
  5. webservice4
  6. Beanutils基本用法
  7. poj[2230]Watchcow 深搜 欧拉回路
  8. LOJ2257 SNOI2017 遗失的答案 容斥、高维前缀和
  9. 《剑指offer》第二十三题(链表中环的入口结点)
  10. python—模块-configparser