Extended win OS detection to include vista and win7

This commit is contained in:
Shyotl
2011-03-27 18:56:30 -05:00
parent 18af6baedd
commit dc62c29af0
5 changed files with 168 additions and 19 deletions

View File

@@ -76,6 +76,75 @@ extern int errno;
static const S32 CPUINFO_BUFFER_SIZE = 16383;
LLCPUInfo gSysCPU;
#if LL_WINDOWS
#ifndef DLLVERSIONINFO
typedef struct _DllVersionInfo
{
DWORD cbSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformID;
}DLLVERSIONINFO;
#endif
#ifndef DLLGETVERSIONPROC
typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
#endif
bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)
{
bool result = false;
const U32 BUFF_SIZE = 32767;
WCHAR tempBuf[BUFF_SIZE];
if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE))
{
std::basic_string<WCHAR> shell32_path(tempBuf);
// Shell32.dll contains the DLLGetVersion function.
// according to msdn its not part of the API
// so you have to go in and get it.
// http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx
shell32_path += TEXT("\\shell32.dll");
HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL
if(hDllInst)
{ // Could successfully load the DLL
DLLGETVERSIONPROC pDllGetVersion;
/*
You must get this function explicitly because earlier versions of the DLL
don't implement this function. That makes the lack of implementation of the
function a version marker in itself.
*/
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst,
"DllGetVersion");
if(pDllGetVersion)
{
// DLL supports version retrieval function
DLLVERSIONINFO dvi;
ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
HRESULT hr = (*pDllGetVersion)(&dvi);
if(SUCCEEDED(hr))
{ // Finally, the version is at our hands
major = dvi.dwMajorVersion;
minor = dvi.dwMinorVersion;
build_number = dvi.dwBuildNumber;
result = true;
}
}
FreeLibrary(hDllInst); // Release DLL
}
}
return result;
}
#endif // LL_WINDOWS
LLOSInfo::LLOSInfo() :
mMajorVer(0), mMinorVer(0), mBuild(0)
{
@@ -98,6 +167,11 @@ LLOSInfo::LLOSInfo() :
mMinorVer = osvi.dwMinorVersion;
mBuild = osvi.dwBuildNumber;
DWORD shell32_major, shell32_minor, shell32_build;
bool got_shell32_version = get_shell32_dll_version(shell32_major,
shell32_minor,
shell32_build);
switch(osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
@@ -122,14 +196,50 @@ LLOSInfo::LLOSInfo() :
else
mOSStringSimple = "Microsoft Windows Server 2003 ";
}
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 1)
{
if(osvi.wProductType == VER_NT_WORKSTATION)
if(osvi.dwMinorVersion == 0)
{
mOSStringSimple = "Microsoft Windows Vista ";
else mOSStringSimple = "Microsoft Windows Vista Server ";
}
else if(osvi.dwMinorVersion == 1)
{
mOSStringSimple = "Microsoft Windows 7 ";
}
if(osvi.wProductType != VER_NT_WORKSTATION)
{
mOSStringSimple += "Server ";
}
///get native system info if available..
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
SYSTEM_INFO si; //System Info object file contains architecture info
PGNSI pGNSI; //pointer object
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
if(NULL != pGNSI) //check if it has failed
pGNSI(&si); //success
else
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
//msdn microsoft finds 32 bit and 64 bit flavors this way..
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
//of windows than this code does (in case it is needed for the future)
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
{
mOSStringSimple += "64-bit ";
}
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
{
mOSStringSimple += "32-bit ";
}
}
else // Use the registry on early versions of Windows NT.
{
mOSStringSimple = "Microsoft Windows (unrecognized) ";
HKEY hKey;
WCHAR szProductType[80];
DWORD dwBufLen;
@@ -170,6 +280,7 @@ LLOSInfo::LLOSInfo() :
csdversion.c_str(),
(osvi.dwBuildNumber & 0xffff));
}
mOSString = mOSStringSimple + tmpstr;
}
break;
@@ -199,6 +310,21 @@ LLOSInfo::LLOSInfo() :
mOSString = mOSStringSimple;
break;
}
std::string compatibility_mode;
if(got_shell32_version)
{
if(osvi.dwMajorVersion != shell32_major
|| osvi.dwMinorVersion != shell32_minor)
{
compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
shell32_major,
shell32_minor,
shell32_build);
}
}
mOSString += compatibility_mode;
#else
struct utsname un;
if(uname(&un) != -1)
@@ -226,8 +352,8 @@ LLOSInfo::LLOSInfo() :
else if (ostype == "Linux")
{
// Only care about major and minor Linux versions, truncate at second '.'
S32 idx1 = mOSStringSimple.find_first_of(".", 0);
S32 idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
std::string simple = mOSStringSimple.substr(0, idx2);
if (simple.length() > 0)
mOSStringSimple = simple;
@@ -393,15 +519,15 @@ LLCPUInfo::LLCPUInfo()
mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
mHasAltivec = info->_Ext.Altivec_Extensions;
mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0);
mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0);
mFamily.assign( info->strFamily );
mCPUString = "Unknown";
#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
out << proc.strCPUName;
if (200 < mCPUMhz && mCPUMhz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
{
out << " (" << mCPUMhz << " MHz)";
out << " (" << mCPUMHz << " MHz)";
}
mCPUString = out.str();
@@ -446,7 +572,7 @@ LLCPUInfo::LLCPUInfo()
if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
&& 200.0 < mhz && mhz < 10000.0)
{
mCPUMhz = (S32)llrint(mhz);
mCPUMHz = (F64)llrint(mhz);
}
if (!cpuinfo["model name"].empty())
mCPUString = cpuinfo["model name"];
@@ -469,9 +595,9 @@ bool LLCPUInfo::hasSSE2() const
return mHasSSE2;
}
S32 LLCPUInfo::getMhz() const
F64 LLCPUInfo::getMHz() const
{
return mCPUMhz;
return mCPUMHz;
}
std::string LLCPUInfo::getCPUString() const
@@ -518,7 +644,7 @@ void LLCPUInfo::stream(std::ostream& s) const
s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
s << "->mCPUMhz: " << mCPUMhz << std::endl;
s << "->mCPUMHz: " << mCPUMHz << std::endl;
s << "->mCPUString: " << mCPUString << std::endl;
}
@@ -595,6 +721,26 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const
}
}
//static
void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
{
#if LL_WINDOWS
MEMORYSTATUSEX state;
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ;
avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ;
#else
//do not know how to collect available memory info for other systems.
//leave it blank here for now.
avail_physical_mem_kb = -1 ;
avail_virtual_mem_kb = -1 ;
#endif
}
void LLMemoryInfo::stream(std::ostream& s) const
{
#if LL_WINDOWS

View File

@@ -81,7 +81,7 @@ public:
bool hasAltivec() const;
bool hasSSE() const;
bool hasSSE2() const;
S32 getMhz() const;
F64 getMHz() const;
// Family is "AMD Duron" or "Intel Pentium Pro"
const std::string& getFamily() const { return mFamily; }
@@ -90,7 +90,7 @@ private:
bool mHasSSE;
bool mHasSSE2;
bool mHasAltivec;
S32 mCPUMhz;
F64 mCPUMHz;
std::string mFamily;
std::string mCPUString;
};
@@ -120,6 +120,9 @@ public:
** be returned.
*/
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
//get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
};

View File

@@ -800,7 +800,7 @@ bool LLAppViewer::init()
minSpecs += "\n";
unsupported = true;
}
if(gSysCPU.getMhz() < minCPU)
if(gSysCPU.getMHz() < minCPU)
{
minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
minSpecs += "\n";
@@ -2358,7 +2358,7 @@ void LLAppViewer::writeSystemInfo()
//need to put in something to lie about this stuff
gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMhz();
gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMHz();
gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();

View File

@@ -627,9 +627,9 @@ void LLFeatureManager::applyBaseMasks()
#if LL_SOLARIS && defined(__sparc) // even low MHz SPARCs are fast
#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here?
if (gSysCPU.getMhz() < 800)
if (gSysCPU.getMHz() < 800)
#else
if (gSysCPU.getMhz() < 1100)
if (gSysCPU.getMHz() < 1100)
#endif
{
maskFeatures("CPUSlow");

View File

@@ -162,7 +162,7 @@ LLViewerJoystick::LLViewerJoystick()
memset(mBtn, 0, sizeof(mBtn));
// factor in bandwidth? bandwidth = gViewerStats->mKBitStat
mPerfScale = 4000.f / gSysCPU.getMhz();
mPerfScale = 4000.f / gSysCPU.getMHz();
}
// -----------------------------------------------------------------------------