#include
#include
#include
#include
#include
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Version.lib")
#ifdef UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif // UNICODE
typedef struct __tagLANGANDCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
}LANGANDCODEPAGE;
typedef LANGANDCODEPAGE* PLANGANDCODEPAGE;
#define VERSION_UNKNOWN TEXT("Unknown")
#define VERSION_UNCORRECT TEXT("Uncorrect")
//校验 是否处于 WOW64模式下
//如果 是 WOW64 即 32位应用程序运行在 64位操作系统下,这时如果要获取 system32真实路径需要关闭 操作系统文件重定向功能
//微软 提供两种 WOW64模式检测机制
//IsWow64Process 方式
BOOL IsWow64WithIsWow64Process(PBOOL bIsWow64)
{
*bIsWow64 = FALSE;
HMODULE hKernel32 = NULL;
BOOL bRes = FALSE;
//IsWow64Process 最小支持的操作系统为 Windows XP with SP2
//所以需要作出兼容性处理
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
do
{
//1.获取kernel32句柄
hKernel32 = ::LoadLibrary(TEXT("Kernel32.dll"));
if ( NULL == hKernel32 )
{
::OutputDebugStringA("--> IsWow64WithIsWow64Process Error 1");
break;
}
//2.获取 IsWow64Process 函数地址
LPFN_ISWOW64PROCESS lpIsWow64Process = (LPFN_ISWOW64PROCESS)::GetProcAddress(hKernel32, "IsWow64Process");
if ( NULL == lpIsWow64Process )
{
::OutputDebugStringA("--> IsWow64WithIsWow64Process Error 2");
break;
}
//3.调用 IsWow64Process
bRes = lpIsWow64Process(::GetCurrentProcess(), bIsWow64);
} while (FALSE);
if (NULL != hKernel32)
{
::FreeLibrary(hKernel32);
hKernel32 = NULL;
}
return bRes;
}
//GetNativeSystemInfo 方式
BOOL IsWow64WithGetNativeSystemInfo(PBOOL bIsWow64)
{
*bIsWow64 = FALSE;
HMODULE hKernel32 = NULL;
SYSTEM_INFO sysInfo = { 0 };
SYSTEM_INFO sysNativeInfo = { 0 };
BOOL bRes = FALSE;
//GetSystemInfo 最小要求系统为 Windows 2000 Professional
//GetNativeSystemInfo 最小要求系统为 Windows XP
//所以不需要作出任何兼容性处理,直接使用两个函数
typedef void (WINAPI *LPFN_GetNativeSystemInfo)(LPSYSTEM_INFO);
do
{
//1.调用 GetSystemInfo
::GetSystemInfo(&sysInfo);
//2.调用 GetNativeSystemInfo获取kernel32句柄
hKernel32 = ::LoadLibrary(TEXT("Kernel32.dll"));
if ( NULL == hKernel32 )
{
::OutputDebugStringA("--> IsWow64WithGetNativeSystemInfo Error 1");
break;
}
LPFN_GetNativeSystemInfo lpGetNativeSystemInfo = (LPFN_GetNativeSystemInfo)::GetProcAddress(hKernel32, "GetNativeSystemInfo");
if ( NULL == lpGetNativeSystemInfo )
{
::OutputDebugStringA("--> IsWow64WithGetNativeSystemInfo Error 2");
break;
}
lpGetNativeSystemInfo(&sysNativeInfo);
//3.分析
/*
根据MSDN的解释:SYSTEM_INFO 中的 wProcessorArchitecture 成员 此值为0时是 IA32,为9 时 是 AMD64
如果32位程序 在 win32系统中 运行,则两个值都是 0,如果在win64 系统运行,则是GetSystemInfo 返回0,
GetNativeSystemInfo 返回9,简而言之 当着两个值不同时就认为程序在 win64系统上运行.
*/
if ( sysInfo.wProcessorArchitecture != sysNativeInfo.wProcessorArchitecture)
{
::OutputDebugStringA("IsWow64WithGetNativeSystemInfo --> WOW64!!");
*bIsWow64 = TRUE;
}
else
{
::OutputDebugStringA("IsWow64WithGetNativeSystemInfo --> NOT WOW64!!");
*bIsWow64 = FALSE;
}
bRes = TRUE;
} while (FALSE);
if (NULL != hKernel32)
{
::FreeLibrary(hKernel32);
hKernel32 = NULL;
}
return bRes;
}
BOOL IsWow64(void)
{
BOOL bIsWow64First = FALSE;
BOOL bIsWow64Second = FALSE;
BOOL bIsWow64 = FALSE;
//1.先使用第一种方式
BOOL bResFirst = IsWow64WithIsWow64Process(&bIsWow64First);
//2.第二种方式
BOOL bResSecond = IsWow64WithGetNativeSystemInfo(&bIsWow64Second);
//3.校验
if ( TRUE == bResFirst )
{
if ( bIsWow64First == bIsWow64Second )
{
::OutputDebugStringA("--> IsWow64 : The same results for the two time.");
bIsWow64 = bIsWow64First;
}
else
{//如果第一个函数执行成功,但是第一个函数返回的结果与第二个不一致时
//以第二种方式检测为准
::OutputDebugStringA("--> IsWow64 : The two execution results are not the same, using the results of the second.");
bIsWow64 = bIsWow64Second;
}
}
else
{//如果第一个函数执行失败,直接使用第二种方式
::OutputDebugStringA("--> IsWow64 : The first failure, using the results of the second.");
bIsWow64 = bIsWow64Second;
}
return bIsWow64;
}
//文件重定向相关
BOOL TWow64EnableWow64FsRedirection(BOOLEAN bWow64FsEnableRedirection)
{
BOOL bRes = FALSE;
HMODULE hKernel32dll = NULL;
do
{
//1.获取 Kernel32.dll 模块句柄
hKernel32dll = ::LoadLibraryA("Kernel32.dll");
if ( NULL == hKernel32dll )
{
::OutputDebugStringA("--> GetWow64EnableWow64FsRedirectionAddr. Get [Kernel32.dll] error.");
break;
}
//2.获取 Wow64EnableWow64FsRedirection 函数地址
typedef BOOLEAN(WINAPI *pFunWow64EnableWow64FsRedirection)(BOOLEAN);
pFunWow64EnableWow64FsRedirection lpWow64EnableWow64FsRedirection = (pFunWow64EnableWow64FsRedirection)::GetProcAddress(hKernel32dll, "Wow64EnableWow64FsRedirection");
if ( NULL == lpWow64EnableWow64FsRedirection )
{
::OutputDebugStringA("--> GetWow64EnableWow64FsRedirectionAddr. Get [Wow64EnableWow64FsRedirection] error.");
break;
}
//3.执行
bRes = lpWow64EnableWow64FsRedirection(bWow64FsEnableRedirection);
if ( FALSE == bRes )
{
DWORD dwCode = ::GetLastError();
char szLog[512] = { 0 };
sprintf_s(szLog, 511, "--> TWow64EnableWow64FsRedirection Call API Error code = %u", dwCode);
::OutputDebugStringA(szLog);
break;
}
::OutputDebugStringA("--> TWow64EnableWow64FsRedirection End(ok)");
} while (FALSE);
if ( NULL != hKernel32dll )
{
::FreeLibrary(hKernel32dll);
hKernel32dll = NULL;
}
return bRes;
}
//获取 system32 文件夹 路径("C:\windows\system32")
BOOL GetSystem32DirPath(LPTSTR lpFullPath, DWORD dwSize)
{
TCHAR szBuf[MAX_PATH + 1] = { 0 };
do
{
//0.GetSystemDirectory
if (0 != ::GetSystemDirectory(lpFullPath, dwSize))
{
::OutputDebugString(lpFullPath);
return TRUE;
}
//1.使用 SHGetSpecialFolderPath //C:\windows
if (TRUE == ::SHGetSpecialFolderPath(NULL, szBuf, CSIDL_WINDOWS, FALSE))
{
::OutputDebugString(szBuf);
break;
}
//2.如果失败使用GetWindowsDirectory //C:\windows
if ( 0 != ::GetWindowsDirectory(szBuf, MAX_PATH) )
{
::OutputDebugString(szBuf);
break;
}
//3.如果都失败 直接认为 c:\\windows
::ZeroMemory(lpFullPath, (MAX_PATH+1)* sizeof(TCHAR));
_tcscpy_s(szBuf, MAX_PATH, TEXT("C:\\windows"));
} while (FALSE);
DWORD dwBufSize = _tcslen(szBuf);
if ( (NULL == lpFullPath) || ( dwSize < dwBufSize) )
{
TCHAR szLog[512] = { 0 };
_stprintf_s(szLog, 511, TEXT("GetSystem32DirPath Failed. Size=%d, OurSize=%d"), dwSize, dwBufSize);
::OutputDebugString(szLog);
return FALSE;
}
_stprintf_s(lpFullPath, dwSize - 1, TEXT("%s\\system32"), szBuf);
::OutputDebugString(lpFullPath);
return TRUE;
}
//获取 ntoskrnl.exe 文件的 “产品版本号”
tstring GetNtosKrnlFileVersion(LPCTSTR lpFullPath)
{
DWORD dwHandle = 0;
DWORD dwFileInfoSize = ::GetFileVersionInfoSize(lpFullPath, &dwHandle);
if (0 == dwFileInfoSize)
{
return tstring(TEXT(""));
}
std::vector sResult(dwFileInfoSize /** sizeof(WCHAR)*/, 0x00);
if (FALSE == ::GetFileVersionInfo(lpFullPath, 0, dwFileInfoSize, &sResult.front()))
{
return tstring(TEXT(""));
}
PLANGANDCODEPAGE lpTranslationPtr = NULL;
UINT uLen = 0;
if (FALSE == ::VerQueryValue(&sResult.front(), TEXT("VarFileInfo\\Translation"), (LPVOID*)&lpTranslationPtr, &uLen))
{
return tstring(TEXT(""));
}
TCHAR szVersionValue[512] = TEXT("");
_stprintf_s(szVersionValue, 511, TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"), lpTranslationPtr[0].wLanguage, lpTranslationPtr[0].wCodePage);
LPTSTR lpInformationPtr = NULL;
if (FALSE == ::VerQueryValue(&sResult.front(), szVersionValue, (LPVOID*)&lpInformationPtr, &uLen))
{
return tstring(TEXT(""));
}
if (_tcslen(lpInformationPtr) <= 0)
{
return tstring(TEXT(""));
}
return tstring(lpInformationPtr);
}
//根据 ntoskrnl产品版本号 获取 主版本号、次版本号、Build号
BOOL GetVersionInfos(tstring tstrVer, LPDWORD lpdwMajorVersion, LPDWORD lpdwMinorVersion, LPDWORD lpdwBuildNumber)
{
//1.主版本号
int nMajorVersionIndex = tstrVer.find(TEXT("."));
if ( tstring::npos == nMajorVersionIndex )
{
return FALSE;
}
tstring tstrMajorVersion = tstrVer.substr(0, nMajorVersionIndex);
//2.次版本号
tstrVer = tstrVer.substr(nMajorVersionIndex + 1);
int nMinorVersionIndex = tstrVer.find(TEXT("."));
if ( tstring::npos == nMinorVersionIndex )
{
return FALSE;
}
tstring tstrMinorVersion = tstrVer.substr(0, nMinorVersionIndex);
//3.Build号
tstrVer = tstrVer.substr(nMinorVersionIndex + 1);
int nBuildIndex = tstrVer.find(TEXT("."));
if ( tstring::npos == nBuildIndex )
{
return FALSE;
}
tstring tstrBuild = tstrVer.substr(0, nBuildIndex);
//4.生成
*lpdwMajorVersion = _ttoi(tstrMajorVersion.c_str());
*lpdwMinorVersion = _ttoi(tstrMinorVersion.c_str());
*lpdwBuildNumber = _ttoi(tstrBuild.c_str());
return TRUE;
}
//获取 ntoskrnl.exe 文件的 “产品版本号”
BOOL GetNtosKrnlFileVersion(LPDWORD lpdwMajorVersion, LPDWORD lpdwMinorVersion, LPDWORD lpdwBuildNumber)
{
BOOL bIsCloseWow64 = FALSE;
BOOL bRes = FALSE;
do
{
//1.校验 WOW64模式
//2.如果处于WOW64模式,禁用文件重定向
if (TRUE == IsWow64())
{
if (FALSE == TWow64EnableWow64FsRedirection(FALSE))
{
break;
}
bIsCloseWow64 = TRUE;
}
//3.获取system32目录路径
TCHAR szPath[MAX_PATH + 1] = { 0 };
if (FALSE == GetSystem32DirPath(szPath, MAX_PATH) )
{
break;
}
tstring tstrNtosKrnl(szPath);
tstrNtosKrnl += TEXT("\\ntoskrnl.exe");
::OutputDebugString(tstrNtosKrnl.c_str());
//4.获取ntoskrnl版本号
tstring tstrResult = GetNtosKrnlFileVersion(tstrNtosKrnl.c_str());
if ((tstring(VERSION_UNKNOWN) == tstrResult) || (tstring(VERSION_UNCORRECT) == tstrResult))
{
break;
}
//////////////////////////////////////////////////////////////////////////
//5.读取 主版本号、次版本号、Build号
if (FALSE == GetVersionInfos(tstrResult, lpdwMajorVersion, lpdwMinorVersion, lpdwBuildNumber))
{
break;
}
//6. 成功 设置标记位
bRes = TRUE;
//LOG
TCHAR szLog[512] = { 0 };
_stprintf_s(szLog, 511, TEXT("Version: %d.%d Build : %d"), *lpdwMajorVersion, *lpdwMinorVersion, *lpdwBuildNumber);
::OutputDebugString(szLog);
} while (FALSE);
if (TRUE == bIsCloseWow64)
{
TWow64EnableWow64FsRedirection(TRUE);
}
return bRes;
}
// 获取 操作系统版本号
DWORD GetVersion(void)
{
OSVERSIONINFO osInfo = { 0 };
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (FALSE == GetVersionEx(&osInfo))
{
return ::GetVersion();
}
DWORD dwMajorVersion = osInfo.dwMajorVersion & 0xFFFFFFFF;
DWORD dwMinorVersion = (osInfo.dwMinorVersion & 0xFFFFFFFF) << 8;
DWORD dwVerTemp = dwMajorVersion | dwMinorVersion;
DWORD dwBuild = (osInfo.dwBuildNumber & 0xFFFFFFFF) << 16;
return (dwBuild | dwVerTemp);
}