32/64 bit 系统的区分

来源:互联网 发布:二维数组与一维数组 编辑:程序博客网 时间:2024/05/18 00:04

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

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 <windows.h>
#include 
<tchar.h>
#include 
<stdio.h>

#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)
         
{
            printf( 
"Microsoft Windows XP Professional x64 Edition ");
         }

         
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) "
            osvi.dwBuildNumber 
& 0xFFFF );         
         
else // Windows NT 4.0 prior to SP6a
         {
            _tprintf( TEXT(
"%s (Build %d) "),
               osvi.szCSDVersion,
               osvi.dwBuildNumber 
& 0xFFFF);
         }


         RegCloseKey( hKey );
      }

      
else // not Windows NT 4.0 
      {
         _tprintf( TEXT(
"%s (Build %d) "),
            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 ");
      }
 
      
break;

      
case VER_PLATFORM_WIN32s:

      printf (
"Microsoft Win32s ");
      
break;
   }

   
return TRUE; 
}
原创粉丝点击