判断操作系统及指定进程是32位还是64位

目录

  • 判断操作系统及指定进程是32位还是64位
  • 背景
  • 函数介绍
    • OpenProcess 函数
    • GetCurrentProcess 函数
    • IsWow64Process 函数
  • 实现原理
  • 编码实现
    • 判断操作系统的位数
    • 判断指定进程的位数
  • 程序测试
  • 总结
  • 参考

判断操作系统及指定进程是32位还是64位

背景

应该很多人开发程序的时候,都会遇到这样的一个功能需求,怎么判断一个进程是32位进程还是64位进程呢?通常,我们的解决方法是,调用IsWow64Process函数进行判断。本文介绍的也是这种方法。

但是,本文的这种方法考虑的更加全面。因为,大都数网上的方法都只是调用IsWow64Process函数来进行判断,这只考虑了64位操作系统,却没有考虑过程序如果运行在32位操作系统,那么刚才的判断方法是否会出错!

本文就完善使用IsWow64Process函数判断指定进程是64位还是32位,完美支持32位操作系统和64位操作系统。现在,把程序的实现思路和实现方法写成文档,分享给大家。

函数介绍

OpenProcess 函数

打开一个已存在的进程对象,并返回进程的句柄。

函数声明

HANDLE OpenProcess(
     DWORD dwDesiredAccess, //渴望得到的访问权限(标志)
     BOOL bInheritHandle,   // 是否继承句柄
     DWORD dwProcessId      // 进程标示符
);

参数

  • dwDesiredAccess [in]
    访问进程对象。 此访问权限将针对进程的安全描述符进行检查。 此参数可以是一个或多个进程访问权限。如果调用者启用了SeDebugPrivilege权限,则无论安全描述符的内容如何,都会授予所请求的访问权限。
  • bInheritHandle [in]
    如果此值为TRUE,则此进程创建的进程将继承该句柄。 否则,进程不会继承此句柄。
  • dwProcessId [in]
    要打开的本地进程的标识符。

返回值

  • 如果函数成功,则返回值是指定进程的打开句柄。
  • 如果函数失败,返回值为NULL。要获取扩展错误信息,请调用GetLastError。

GetCurrentProcess 函数

获取当前程序进程的句柄。

函数声明

HANDLE WINAPI GetCurrentProcess(void);

参数

  • 无参数

返回值

  • 返回当前程序进程的句柄。

IsWow64Process 函数

判断指定的进程是否在WOW64下运行。

函数声明

BOOL WINAPI IsWow64Process(
     _In_  HANDLE hProcess,
     _Out_ PBOOL  Wow64Process
);

参数

  • hProcess [in]
    过程的句柄。 句柄必须具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION权限。 有关更多信息,请参阅流程安全和访问权限。
  • Wow64Process [out]
    指向如果进程在WOW64下运行时设置为TRUE的值的指针。 如果进程在32位Windows下运行,则该值设置为FALSE。 如果进程是在64位Windows下运行的64位应用程序,则该值也设置为FALSE。

返回值

  • 如果函数成功,则返回值为非零值。
  • 如果函数失败,返回值为零。 要获取扩展错误信息,请调用GetLastError。

实现原理

先简单介绍下什么是WOW64,WOW64 (Windows-on-Windows 64-bit)是一个Windows操作系统的子系统,它为现有的 32 位应用程序提供了 32 位的模拟,可以使大多数 32 位应用程序在无需修改的情况下运行在 Windows 64 位版本上。也就是说,WOW64就是一个 64 位操作系统模拟 32 位操作系统的一个子系统,而且32位程序都运行在它上面。

那么,WIN32 API函数 IsWow64Process,就是判断指定程序是否运行在 WOW64 模拟系统中。而且,根据文档可知:

OS 32bits OS 64BITS
32bits process FALSE TRUE
64bits process ERROR FALSE

上面意思是说:

  • 使用IsWow64Process在32位操作系统上获取32位进程的返回结果是FALSE

  • 使用IsWow64Process在64位操作系统上获取32位进程的返回结果是TRUE

  • 使用IsWow64Process在32位操作系统上获取64位进程的返回结果是ERROR,因为64位程序不能在32位系统上运行

  • 使用IsWow64Process在64位操作系统上获取64位进程的返回结果是FALSE

也就是说,如果我们要写一个判断进程位数的程序,还要能在32位系统和64位系统上运行,那么就必须先判断操作系统的位数。

判断操作系统位数的原理是:

利用上述的结果,对于32位的进程,在32位系统上,IsWow64Process返回FALSE,而64位系统返回TRUE。而且,我们程序本身就是32位,只要我们获取程序自身的进程句柄,然后传入IsWow64Process函数中判断是否在仿真环境中,根据返回结果可以知道32位系统还是64位系统。

那么,判断全系统上,进程的位数的原理是:

  • 程序自身是32位进程。首先,先判断操作操作系统的位数。若是32位操作系统,那么它上面的所有进程都是32位的

  • 若是64位进程,那么就打开指定进程获取进程句柄。然后将进程句柄传递给IsWow64Process函数,进行判断。若是返回TRUE,则说明进程运行在WOW64模拟环境中,是一个32位进程;否则,是64位进程

编码实现

判断操作系统的位数

BOOL Is64BitsOperateSystem()
{
	// 判断当前计算机操作系统是32位操作系统还是64位操作系统

	BOOL bWow64Process = FALSE;
	// 获取当前程序进程句柄
	HANDLE hProcess = ::GetCurrentProcess();
	if (NULL == hProcess)
	{
		ShowError("OpenProcess");
		return bWow64Process;
	}

	// 判断进程是否处于WOW64仿真环境中
	::IsWow64Process(hProcess, &bWow64Process);

	return bWow64Process;
}

判断指定进程的位数

BOOL Is64BitsProcess(DWORD dwProcessId)
{
	// 判断64位系统下, 进程指定是32位还是64位

	// 先判断计算机操作系统位数, 32位系统只能执行32位进程
	if (FALSE == Is64BitsOperateSystem)
	{
		return FALSE;
	}

	BOOL bWow64Process = FALSE;
	// 打开进程, 获取进程句柄
	HANDLE hProcess = NULL;
	hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
	if (NULL == hProcess)
	{
		ShowError("OpenProcess");
		return bWow64Process;
	}

	// 判断进程是否处于WOW64仿真环境中
	::IsWow64Process(hProcess, &bWow64Process);
	
	return bWow64Process;
}

程序测试

在 main 函数中调用上述封装好的函数进行测试,main 函数为:

int _tmain(int argc, _TCHAR* argv[])
{
	// 11360 --> 32位进程
	if (Is64BitsProcess(11360))
	{
		printf("32 bits\n");
	}
	else
	{
		printf("64 bits\n");
	}
	// 7400 --> 64位进程
	if (Is64BitsProcess(7400))
	{
		printf("32 bits\n");
	}
	else
	{
		printf("64 bits\n");
	}

	system("pause");
	return 0;
}

测试结果

测试的例子中,进程PID为11360的是32位程序,PDI为7400的是64位程序。

运行程序,程序判断正确。

判断操作系统及指定进程是32位还是64位_第1张图片

总结

很多人使用IsWow64Process来判断进程的位数,往往会忽略考虑32位系统的情况,而造成程序在32位系统上运行出错。所以,这一点一定要考虑全面。

参考

参考自《Windows黑客编程技术详解》一书

你可能感兴趣的:(windows,c++,windows,wow64,dev,win32)