判断当前Windows XP操作系统是32位还是64位的方法

昨天在调查怎样区分Windows XP32位和64位的问题,在网上找了一下,大家常用的有两种方法。

方法一、通过指针来判断。

32位操作系统上指针长是4个字节,而在64位系统上指针为8个字节。

 

方法二、通过环境变量识别。

设计64位Windows XP,能否很好地兼容32位程序是它的重中之重,安装64位Windows XP后,我能看到系统盘根目下有一个特殊的文件——Program Files(x86),在系统环境变量中也会出现这个设置。

具体的就是GetEnvironmentVariableAPIProgramFiles(x86),如果量存在,64位,否32位。

 

依据是:

WOW64 Implementation Details

The WOW64 emulator runs in user mode, provides an interface between the 32-bit version of Ntdll.dll and the kernel of the processor, and it intercepts kernel calls. The emulator consists of the following DLLs:

·                     Wow64.dll provides the core emulation infrastructure and the thunks for the Ntoskrnl.exe entry-point functions.

·                     Wow64Win.dll provides thunks for the Win32k.sys entry-point functions.

·                     Wow64Cpu.dll provides x86 instruction emulation on Itanium processors. It executes mode-switch instructions on the processor. This DLL is not necessary for x64 processors because they execute x86-32 instructions at full clock speed.

Along with the 64-bit version of Ntdll.dll, these are the only 64-bit binaries that can be loaded into a 32-bit process.

At startup, Wow64.dll loads the x86 version of Ntdll.dll and runs its initialization code, which loads all necessary 32-bit DLLs. Almost all 32-bit DLLs are unmodified copies of 32-bit Windows binaries. However, some of these DLLs are written to behave differently on WOW64 than they do on 32-bit Windows, usually because they share memory with 64-bit system components. All user mode address space above the 32-bit limits (2 GB for most applications, 4 GB for applications marked with the IMAGE_FILE_LARGE_ADDRESS_AWARE flag in the image header) is reserved by the system.

Instead of using the x86 system-service call sequence, 32-bit binaries that make system calls are rebuilt to use a custom calling sequence. This new sequence is inexpensive for WOW64 to intercept because it remains entirely in user mode. When the new calling sequence is detected, the WOW64 CPU transitions back to native 64-bit mode and calls into Wow64.dll. Thunking is done in user mode to reduce the impact on the 64-bit kernel, and to reduce the risk of a bug in the thunk that causes a kernel-mode crash, data corruption, or a security hole. The thunks extract arguments from the 32-bit stack, extend them to 64 bits, then make the native system call.

Environment Variables

Environment variables are changed for compatibility when a 32-bit process is created by a 64-bit process, or when a 64-bit process is created by a 32-bit process. WOW64 changes the following environment variables.

Environment Variable

64-bit Value

32-bit Value

PROCESSOR_ARCHITECTURE

Native (AMD64 or IA64)

x86

PROCESSOR_ARCHITEW6432

 N/A

%PROCESSOR_ARCHITECTURE%

ProgramFiles

%ProgramFiles%

%ProgramFiles(x86)%

ProgramW6432

 N/A

%ProgramFiles%

CommonProgramFiles

%CommonProgramFiles%

%CommonProgramFiles(x86)%

CommonProgramW6432

 N/A

%CommonProgramFiles%

Global Hooks

SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, a 32-bit application must call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application must call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. Also, the 32-bit and 64-bit DLLs must have different names.

出处:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/wow64_implementation_details.asp

 

上述两种方法,第一种是通过C++指针变量的大小来判断,主观意识很强;第二种通过64位操作系统的对32位软件支持的特性来判断,方法比较巧妙,但是好像说服力不是很强。如果微软做出变更,这种方法就有些立不住脚。

 

方法三、通过微软提供的API函数判断。

Getting the System Version

The following example uses the GetVersionEx, GetSystemMetrics, and GetNativeSystemInfo functions to determine the version information of the currently running operating system. The code outputs the information to the console.

 

Relying on version information is not the best way to test for a feature. Instead, refer to the documentation for the feature of interest. For more information on common techniques for feature detection, see Operating System Version.

If you must require a particular operating system, be sure to use it as a minimum supported version, rather than design the test for the one operating system. This way, your detection code will continue to work on future versions of Windows.

#include 
#include 
#include 

#define BUFSIZE 80

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);

int __cdecl _tmain()
{
   OSVERSIONINFOEX osvi;
   SYSTEM_INFO si;
   PGNSI pGNSI;
   BOOL bOsVersionInfoEx;

   ZeroMemory(&si, sizeof(SYSTEM_INFO));
   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

   // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
   // If that fails, try using the OSVERSIONINFO structure.

   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

   if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
   {
      osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
      if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
         return FALSE;
   }

   // Call GetNativeSystemInfo if supported
   // or GetSystemInfo otherwise.

   pGNSI = (PGNSI) GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), 
      "GetNativeSystemInfo");
   if(NULL != pGNSI)
      pGNSI(&si);
   else GetSystemInfo(&si);

   switch (osvi.dwPlatformId)
   {
      // Test for the Windows NT product family.

      case VER_PLATFORM_WIN32_NT:

      // Test for the specific product.

      if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
      {
         if( osvi.wProductType == VER_NT_WORKSTATION )
             printf ("Windows Vista ");
         else printf ("Windows Server /"Longhorn/" " );
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
      {
         if( GetSystemMetrics(SM_SERVERR2) )
            printf( "Microsoft Windows Server 2003 /"R2/" ");
         else if( osvi.wProductType == VER_NT_WORKSTATION &&
            si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
         {
            
         }
         else printf ("Microsoft Windows Server 2003, ");
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
         printf ("Microsoft Windows XP ");

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
         printf ("Microsoft Windows 2000 ");

      if ( osvi.dwMajorVersion <= 4 )
         printf ("Microsoft Windows NT ");

      // Test for specific product on Windows NT 4.0 SP6 and later.
      if( bOsVersionInfoEx )
      {
         // Test for the workstation type.
         if ( osvi.wProductType == VER_NT_WORKSTATION &&
              si.wProcessorArchitecture!=PROCESSOR_ARCHITECTURE_AMD64)
         {
            if( osvi.dwMajorVersion == 4 )
               printf ( "Workstation 4.0 " );
            else if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
               printf ( "Home Edition " );
            else printf ( "Professional " );
         }
            
         // Test for the server type.
         else if ( osvi.wProductType == VER_NT_SERVER || 
                   osvi.wProductType == VER_NT_DOMAIN_CONTROLLER )
         {
            if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==2)
            {
               if ( si.wProcessorArchitecture ==
                    PROCESSOR_ARCHITECTURE_IA64 )
               {
                   if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                      printf ( "Datacenter Edition "
                               "for Itanium-based Systems" );
                   else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                      printf ( "Enterprise Edition "
                               "for Itanium-based Systems" );
               }

               else if ( si.wProcessorArchitecture ==
                         PROCESSOR_ARCHITECTURE_AMD64 )
               {
                   if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                      printf ( "Datacenter x64 Edition " );
                   else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                      printf ( "Enterprise x64 Edition " );
                   else printf( "Standard x64 Edition " );
               }

               else
               {
                   if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                      printf ( "Datacenter Edition " );
                   else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                      printf ( "Enterprise Edition " );
                   else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
                      printf ( "Web Edition " );
                   else printf ( "Standard Edition " );
               }
            }
            else if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)
            {
               if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                  printf ( "Datacenter Server " );
               else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                  printf ( "Advanced Server " );
               else printf ( "Server " );
            }
            else  // Windows NT 4.0 
            {
               if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                  printf ("Server 4.0, Enterprise Edition " );
               else printf ( "Server 4.0 " );
            }
         }
      }
      // Test for specific product on Windows NT 4.0 SP5 and earlier
      else  
      {
         HKEY hKey;
         TCHAR szProductType[BUFSIZE];
         DWORD dwBufLen=BUFSIZE*sizeof(TCHAR);
         LONG lRet;

         lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
            TEXT("SYSTEM//CurrentControlSet//Control//"
                 "ProductOptions"), 0, KEY_QUERY_VALUE, &hKey );
         if( lRet != ERROR_SUCCESS )
            return FALSE;

         lRet = RegQueryValueEx( hKey, TEXT("ProductType"),
            NULL, NULL, (LPBYTE) szProductType, &dwBufLen);
         RegCloseKey( hKey );

         if( (lRet != ERROR_SUCCESS) ||
             (dwBufLen > BUFSIZE*sizeof(TCHAR)) )
            return FALSE;

         if ( lstrcmpi( TEXT("WINNT"), szProductType) == 0 )
            printf( "Workstation " );
         if ( lstrcmpi( TEXT("LANMANNT"), szProductType) == 0 )
            printf( "Server " );
         if ( lstrcmpi( TEXT("SERVERNT"), szProductType) == 0 )
            printf( "Advanced Server " );
         printf( "%d.%d ", osvi.dwMajorVersion, osvi.dwMinorVersion );
      }

      // Display service pack (if any) and build number.

      if( osvi.dwMajorVersion == 4 && 
          lstrcmpi( osvi.szCSDVersion, TEXT("Service Pack 6") ) == 0 )
      { 
         HKEY hKey;
         LONG lRet;

         // Test for SP6 versus SP6a.
         lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
            TEXT("SOFTWARE//Microsoft//Windows NT//CurrentVersion//"
                 "Hotfix//Q246009"), 0, KEY_QUERY_VALUE, &hKey );
         if( lRet == ERROR_SUCCESS )
            printf( "Service Pack 6a (Build %d)/n", 
            osvi.dwBuildNumber & 0xFFFF );         
         else // Windows NT 4.0 prior to SP6a
         {
            _tprintf( TEXT("%s (Build %d)/n"),
               osvi.szCSDVersion,
               osvi.dwBuildNumber & 0xFFFF);
         }

         RegCloseKey( hKey );
      }
      else // not Windows NT 4.0 
      {
         _tprintf( TEXT("%s (Build %d)/n"),
            osvi.szCSDVersion,
            osvi.dwBuildNumber & 0xFFFF);
      }

      break;

      // Test for the Windows Me/98/95.
      case VER_PLATFORM_WIN32_WINDOWS:

      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
      {
          printf ("Microsoft Windows 95 ");
          if (osvi.szCSDVersion[1]=='C' || osvi.szCSDVersion[1]=='B')
             printf("OSR2 " );
      } 

      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
      {
          printf ("Microsoft Windows 98 ");
          if ( osvi.szCSDVersion[1]=='A' || osvi.szCSDVersion[1]=='B')
             printf("SE " );
      } 

      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
      {
          printf ("Microsoft Windows Millennium Edition/n");
      } 
      break;

      case VER_PLATFORM_WIN32s:

      printf ("Microsoft Win32s/n");
      break;
   }
   return TRUE; 
}
出处:http://msdn2.microsoft.com/en-us/library/ms724429.aspx

一些系统信息问题可以参照下面的内容

SYSTEM_INFO

 

Contains information about the current computer system.

This includes the architecture and type of the processor,

the number of processors in the system, the page size,

and other such information.

 
typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId;
struct {
WORD wProcessorArchitecture;
WORD wReserved;
};
};
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision; } SYSTEM_INFO;
Members
dwOemId

An obsolete member that is retained for compatibility with Windows NT 3.5 and earlier. New applications should use the wProcessorArchitecture branch of the union.

Windows Me/98/95:  The system always sets this member to zero, the value defined for PROCESSOR_ARCHITECTURE_INTEL.
wProcessorArchitecture
The processor architecture. This member can be one of the following values.
Value Meaning
PROCESSOR_ARCHITECTURE_AMD64
9
x64 (AMD or Intel)
PROCESSOR_ARCHITECTURE_IA64
6
Intel Itanium Processor Family (IPF)
PROCESSOR_ARCHITECTURE_INTEL
0
x86
PROCESSOR_ARCHITECTURE_UNKNOWN
0xffff
Unknown processor.
wReserved
This member is reserved for future use.
dwPageSize
The page size and the granularity of page protection and commitment. This is the page size used by the VirtualAlloc function.
lpMinimumApplicationAddress
A pointer to the lowest memory address accessible to applications and dynamic-link libraries (DLLs).
lpMaximumApplicationAddress
A pointer to the highest memory address accessible to applications and DLLs.
dwActiveProcessorMask
A mask representing the set of processors configured into the system. Bit 0 is processor 0; bit 31 is processor 31.
dwNumberOfProcessors
The number of processors in the system.
dwProcessorType
An obsolete member that is retained for compatibility. Use the wProcessorArchitecture, wProcessorLevel, and wProcessorRevision members to determine the type of processor.
Name Value
PROCESSOR_INTEL_386 386
PROCESSOR_INTEL_486 486
PROCESSOR_INTEL_PENTIUM 586
PROCESSOR_INTEL_IA64 2200
PROCESSOR_AMD_X8664 8664
dwAllocationGranularity
The granularity for the starting address at which virtual memory can be allocated. For more information, see VirtualAlloc.
wProcessorLevel
The architecture-dependent processor level. It should be used only for display purposes. To determine the feature set of a processor, use the IsProcessorFeaturePresent function.

If wProcessorArchitecture is PROCESSOR_ARCHITECTURE_INTEL, wProcessorLevel is defined by the CPU vendor.

If wProcessorArchitecture is PROCESSOR_ARCHITECTURE_IA64, wProcessorLevel is set to 1.

wProcessorRevision
The architecture-dependent processor revision. The following table shows how the revision value is assembled for each type of processor architecture.
Processor Value
Intel Pentium, Cyrix, or NextGen 586 The high byte is the model and the low byte is the stepping. For example, if the value is xxyy, the model number and stepping can be displayed as follows:

Model xx, Stepping yy

Intel 80386 or 80486 A value of the form xxyz.

If xx is equal to 0xFF, y - 0xA is the model number, and z is the stepping identifier.

If xx is not equal to 0xFF, xx + 'A' is the stepping letter and yz is the minor stepping.

Requirements

Client

Requires Windows Vista, Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, or Windows 95.

Server

Requires Windows Server 2008, Windows Server 2003, Windows 2000 Server, or Windows NT Server.

Header

Declared in Winbase.h; include Windows.h.

See Also

GetSystemInfo
MapViewOfFile
MapViewOfFileEx

出处: http://msdn2.microsoft.com/en-us/library/ms724958.aspx

 

上述三种方法中还是推荐第三种,原因很简单。就是有官方提供的文档,可以大胆的使用,不用担心由于Microsoft打补丁而导致程序运行异常。

 

第一种方法咋一看比较巧妙,运用指针的大小判断,简单实用。但如果使用过操作64位系统的开发人员一眼就能看出问题所在。由于,64位操作系统要兼容32为的应用程序,因此当32位应用程序运行在64位操作系统时,指针的大小仍然是4个字节。所以,该方法不能判断当前操作系统是否是64位还是32位。

 

第二种方法显然是知道64位系统兼容32位的应用程序而想出的一种“曲线救国”的方法。由于,Microsoft官方已经提供了直接判断的函数,所以这种“曲线救国”的路线显得更加弯曲,呵呵。

你可能感兴趣的:(技术文章)