跟Google学写代码--Chromium/base--windows_version源码学习及应用

Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。 前面写道: 《跟Google学写代码–Chromium/base–stl_util源码学习及应用》

今天与大家分享的就是Chromium下base中的windows_version,对于你的win32应用程序一定会有很多的帮助。

1 定义version枚举

enum Version {
  VERSION_PRE_XP = 0,  // Not supported.
  VERSION_XP,
  VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2.
  VERSION_VISTA,       // Also includes Windows Server 2008.
  VERSION_WIN7,        // Also includes Windows Server 2008 R2.
  VERSION_WIN8,        // Also includes Windows Server 2012.
  VERSION_WIN8_1,      // Code named Windows Blue
  VERSION_WIN_LAST,    // Indicates error condition.};
enum VersionType {
  SUITE_HOME,
  SUITE_PROFESSIONAL,
  SUITE_SERVER,
  SUITE_LAST,
};

2 定义 OSInfo类 a. 通过BASE_EXPORT定义为导出类 b. 将OSInfo()和 ~OSInfo()声明为私有,即我们要的单例模式

class BASE_EXPORT OSInfo { public:  struct VersionNumber {    int major;    int minor;    int build;
  };  struct ServicePack {    int major;    int minor;
  };  enum WindowsArchitecture {
    X86_ARCHITECTURE,
    X64_ARCHITECTURE,
    IA64_ARCHITECTURE,
    OTHER_ARCHITECTURE,
  };  enum WOW64Status {
    WOW64_DISABLED,
    WOW64_ENABLED,
    WOW64_UNKNOWN,
  };  static OSInfo* GetInstance();

  Version version() const { return version_; }
  VersionNumber version_number() const { return version_number_; }
  VersionType version_type() const { return version_type_; }
  ServicePack service_pack() const { return service_pack_; }
  WindowsArchitecture architecture() const { return architecture_; }  int processors() const { return processors_; }
  size_t allocation_granularity() const { return allocation_granularity_; }
  WOW64Status wow64_status() const { return wow64_status_; }
  std::string processor_model_name();  static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); private:  OSInfo();
  ~OSInfo();

  Version version_;
  VersionNumber version_number_;
  VersionType version_type_;
  ServicePack service_pack_;
  WindowsArchitecture architecture_;  int processors_;
  size_t allocation_granularity_;
  WOW64Status wow64_status_;
  std::string processor_model_name_;

  DISALLOW_COPY_AND_ASSIGN(OSInfo);
};// Because this is by far the most commonly-requested value from the above// singleton, we add a global-scope accessor here as syntactic sugar.BASE_EXPORT Version GetVersion();

}  // namespace win}  // namespace base

3 GetInstance()的实现 这里用到了InterlockedCompareExchangePointer: Provides compiler intrinsic support for the Win32 Platform SDK InterlockedCompareExchangePointer function.

OSInfo* OSInfo::GetInstance() {  static OSInfo* info;  if (!info) {
    OSInfo* new_info = new OSInfo();    if (InterlockedCompareExchangePointer(        reinterpret_cast<PVOID*>(&info), new_info, NULL)) {      delete new_info;
    }
  }  return info;
}

这里补充一下,delete new_info后,最好把new_info置为nullptr。

4 获取WOW64状态的实现 最主要的是这行: GetProcAddress(GetModuleHandle(L”kernel32.dll”), “IsWow64Process”));

可以通过加载Kernel32来动态判断 当前操作系统32bit还是64bit。

OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) {  typedef BOOL (WINAPI* IsWow64ProcessFunc)(HANDLE, PBOOL);
  IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
      GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));  if (!is_wow64_process)    return WOW64_DISABLED;
  BOOL is_wow64 = FALSE;  if (!(*is_wow64_process)(process_handle, &is_wow64))    return WOW64_UNKNOWN;  return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
}

应用: 简单的使用:

int main(int argc, char* argv[]) {  int version = base::win::OSInfo::GetInstance()->version();  std::cout << "VERSION_PRE_XP = 0," << std::endl;  std::cout << "VERSION_SERVER_2003 = 1," << std::endl;  std::cout << "VERSION_VISTA = 2," << std::endl;  std::cout << "VERSION_WIN7 = 3," << std::endl;  std::cout << "VERSION_WIN8 = 4," << std::endl;  std::cout << "VERSION_WIN8_1 = 5," << std::endl;  std::cout << "VERSION_WIN_LAST = 6," << std::endl;  std::cout << "My Windows Version is: " << version << std::endl << std::endl;  std::string processor_model_name = base::win::OSInfo::GetInstance()->processor_model_name();  std::cout << "My Processor Model Name is: " << processor_model_name << std::endl << std::endl;  int wow64_status = base::win::OSInfo::GetInstance()->wow64_status();  std::cout << "WOW64_DISABLED = 0," << std::endl;  std::cout << "WOW64_ENABLED = 1," << std::endl;  std::cout << "WOW64_UNKNOWN = 2," << std::endl;  std::cout << "My wow64_status is: " << wow64_status << std::endl << std::endl;




  base::win::OSInfo::VersionNumber version_number = base::win::OSInfo::GetInstance()->version_number();  std::cout << "My Version Number: " << std::endl;  std::cout << " major: " << version_number.major << std::endl;  std::cout << " minor: " << version_number.minor << std::endl;  std::cout << " build: " << version_number.build << std::endl;

  system("pause");  return 0;
}

输出结果:

VERSION_PRE_XP = 0,VERSION_SERVER_2003 = 1,VERSION_VISTA = 2,VERSION_WIN7 = 3,VERSION_WIN8 = 4,VERSION_WIN8_1 = 5,VERSION_WIN_LAST = 6,
My Windows Version is: 5

My Processor Model Name is: Intel(R) Core(TM) i7-5500U CPU @ 2.40GHzWOW64_DISABLED = 0,WOW64_ENABLED = 1,WOW64_UNKNOWN = 2,
My wow64_status is: 1

My Version Number:
 major: 6
 minor: 2
 build: 9200

插曲 一个坑儿:

一个VS中有好几个工程,在运行我们想要运行的项目的时候,出现上图中的错误。

如果你不够细心,你就以为是库的版本不对,比如库是64位,而你运行的是32位程序。。。。。。 但是你看编译库的工程也是32位的,这时候就有点发蒙。。。。。 蓦然回首,你没有把想要运行的程序设置为启动项,而且把那个库的工程设置为了启动项。

原文发布于微信公众号 - 程序员的酒和故事(cppdabaojian)

原文发表时间:2017-01-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SpringSpace.cn

在 ubuntu 12.10 中安装 opensips 1.8.2

解压软件包: tar -zxvf opensips-1.8.2_src.tar.gz

1912
来自专栏代码GG之家

android native内存检测方案(二)

android native 代码内存泄露 定位方案(一) 什么是 AddressSanitizer clang 是一个 C、C++、Objective-C 编...

68910
来自专栏java一日一条

彻底理解 Android Binder 通信架构

roid 6.0的源码剖析, 本文深度剖析Binder IPC过程, 这绝对是一篇匠心巨作,从Java framework到Native,再到Linux Ker...

8942
来自专栏微服务那些事儿

Spring Cloud 系列-事件监听

强推一波:https://segmentfault.com/ls/1650000011386794

2164
来自专栏杨建荣的学习笔记

dg broker校验失败的一个奇怪问题(二) (r8笔记第51天)

对昨天提出的问题做了一个简单的分析和排查,也算是有了一个交代,上一篇文章在 dg broker校验失败的一个奇怪问题 我查看了最近的日志,发现在半个月以前有一...

3515
来自专栏Kubernetes

Kubernetes Nginx Ingress Controller源码分析

main controllers/nginx/pkg/cmd/controller/main.go:29 func main() { // start a ...

49610
来自专栏Android中高级开发

Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索...

1151
来自专栏Urahara Blog

Redis Hacking Tips

1745
来自专栏10km的专栏

linux下用cmake对caffe静态编译时-static-libstdc++参数无效的问题

以下是用于cmake 生成 Makefile文件对Caffe进行静态库连接编译的shell脚本, #!/bin/bash # cmake 静态编译 caffe-...

5956
来自专栏小白安全

渗透测试利器-大数量IP地址以及端口扫描

渗透测试利器  IP 段 端口扫描 利器一: 把IP段用以下格式放到url里 https://censys.io/ipv4?q=ip:[221.133.11.0...

4805

扫码关注云+社区