1
This commit is contained in:
310
tier0/systeminformation.cpp
Normal file
310
tier0/systeminformation.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "pch_tier0.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/systeminformation.h"
|
||||
|
||||
#ifdef IS_WINDOWS_PC
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PrivateType( xxx ) ValvePrivateType_##xxx
|
||||
|
||||
typedef enum { SystemPerformanceInformation = 2 }
|
||||
PrivateType( SYSTEM_INFORMATION_CLASS );
|
||||
|
||||
typedef LONG PrivateType( NTSTATUS );
|
||||
|
||||
typedef PrivateType( NTSTATUS ) ( WINAPI * PrivateType( NtQuerySystemInformation ) )
|
||||
(
|
||||
/*IN*/ PrivateType( SYSTEM_INFORMATION_CLASS ) SystemInformationClass,
|
||||
/*OUT*/ PVOID SystemInformation,
|
||||
/*IN*/ ULONG SystemInformationLength,
|
||||
/*OUT*/ PULONG ReturnLength /*OPTIONAL*/
|
||||
);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LARGE_INTEGER IdleProcessTime;
|
||||
LARGE_INTEGER IoTransferCount[3];
|
||||
ULONG IoOperationCount[3];
|
||||
ULONG AvailablePages;
|
||||
ULONG CommittedPages;
|
||||
ULONG CommitLimit;
|
||||
ULONG u00683;
|
||||
ULONG u00684;
|
||||
ULONG u00685;
|
||||
ULONG u00686;
|
||||
ULONG u00687;
|
||||
ULONG u00688;
|
||||
ULONG u00689;
|
||||
ULONG u00690;
|
||||
ULONG u00691;
|
||||
ULONG u00692;
|
||||
ULONG u00693;
|
||||
ULONG u00694;
|
||||
ULONG u00695;
|
||||
ULONG u00696;
|
||||
ULONG PagedPoolPages;
|
||||
ULONG NonPagedPoolPages;
|
||||
ULONG PagedPoolAllocs;
|
||||
ULONG PagedPoolFrees;
|
||||
ULONG NonPagedPoolAllocs;
|
||||
ULONG NonPagedPoolFrees;
|
||||
ULONG FreeSystemPtes;
|
||||
ULONG u00704;
|
||||
ULONG u00705;
|
||||
ULONG u00706;
|
||||
ULONG NonPagedPoolLookasideHits;
|
||||
ULONG PagedPoolLookasideHits;
|
||||
ULONG FreePagedPoolPages;
|
||||
ULONG u00710;
|
||||
ULONG u00711;
|
||||
ULONG u00712;
|
||||
ULONG uCounters[34];
|
||||
}
|
||||
PrivateType( SYSTEM_PERFORMANCE_INFORMATION );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Cached information about a dll proc
|
||||
//
|
||||
class CSysCallCacheEntry
|
||||
{
|
||||
public:
|
||||
CSysCallCacheEntry();
|
||||
~CSysCallCacheEntry();
|
||||
|
||||
public:
|
||||
bool IsInitialized() const;
|
||||
SYSTEM_CALL_RESULT_t CallResult() const;
|
||||
|
||||
SYSTEM_CALL_RESULT_t InitializeLoadModule( _TCHAR *pszModule, char *pszFunction );
|
||||
SYSTEM_CALL_RESULT_t InitializeFindModule( _TCHAR *pszModule, char *pszFunction );
|
||||
SYSTEM_CALL_RESULT_t InitializeFindProc( HMODULE hModule, char *pszFunction );
|
||||
|
||||
void SetFailed( SYSTEM_CALL_RESULT_t eResult );
|
||||
void Reset();
|
||||
|
||||
template < typename FN >
|
||||
FN GetFunction() const;
|
||||
|
||||
protected:
|
||||
SYSTEM_CALL_RESULT_t m_eResult;
|
||||
FARPROC m_pfnSysCall;
|
||||
HMODULE m_hModule;
|
||||
bool m_bInitialized;
|
||||
bool m_bFreeModule;
|
||||
};
|
||||
|
||||
struct CSysCallCacheEntry_LoadModule : public CSysCallCacheEntry
|
||||
{
|
||||
CSysCallCacheEntry_LoadModule( _TCHAR *pszModule, char *pszFunction ) { InitializeLoadModule( pszModule, pszFunction ); }
|
||||
};
|
||||
struct CSysCallCacheEntry_FindModule : public CSysCallCacheEntry
|
||||
{
|
||||
CSysCallCacheEntry_FindModule( _TCHAR *pszModule, char *pszFunction ) { InitializeFindModule( pszModule, pszFunction ); }
|
||||
};
|
||||
struct CSysCallCacheEntry_FindProc : public CSysCallCacheEntry
|
||||
{
|
||||
CSysCallCacheEntry_FindProc( HMODULE hModule, char *pszFunction ) { InitializeFindProc( hModule, pszFunction ); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
CSysCallCacheEntry::CSysCallCacheEntry() :
|
||||
m_eResult( SYSCALL_SUCCESS ),
|
||||
m_pfnSysCall( NULL ),
|
||||
m_hModule( NULL ),
|
||||
m_bInitialized( false ),
|
||||
m_bFreeModule( false )
|
||||
{
|
||||
}
|
||||
|
||||
CSysCallCacheEntry::~CSysCallCacheEntry()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool CSysCallCacheEntry::IsInitialized() const
|
||||
{
|
||||
return m_bInitialized;
|
||||
}
|
||||
|
||||
SYSTEM_CALL_RESULT_t CSysCallCacheEntry::CallResult() const
|
||||
{
|
||||
return m_eResult;
|
||||
}
|
||||
|
||||
SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeLoadModule( _TCHAR *pszModule, char *pszFunction )
|
||||
{
|
||||
m_bInitialized = true;
|
||||
|
||||
m_hModule = ::LoadLibrary( pszModule );
|
||||
m_bFreeModule = true;
|
||||
if ( !m_hModule )
|
||||
return m_eResult = SYSCALL_NODLL;
|
||||
|
||||
return InitializeFindProc( m_hModule, pszFunction );
|
||||
}
|
||||
|
||||
SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeFindModule( _TCHAR *pszModule, char *pszFunction )
|
||||
{
|
||||
m_bInitialized = true;
|
||||
|
||||
m_hModule = ::GetModuleHandle( pszModule );
|
||||
m_bFreeModule = false;
|
||||
if ( !m_hModule )
|
||||
return m_eResult = SYSCALL_NODLL;
|
||||
|
||||
return InitializeFindProc( m_hModule, pszFunction );
|
||||
}
|
||||
|
||||
SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeFindProc( HMODULE hModule, char *pszFunction )
|
||||
{
|
||||
m_bInitialized = true;
|
||||
|
||||
m_pfnSysCall = GetProcAddress( hModule, pszFunction );
|
||||
if ( !m_pfnSysCall )
|
||||
return m_eResult = SYSCALL_NOPROC;
|
||||
|
||||
return m_eResult = SYSCALL_SUCCESS;
|
||||
}
|
||||
|
||||
void CSysCallCacheEntry::Reset()
|
||||
{
|
||||
if ( m_bInitialized )
|
||||
{
|
||||
if ( m_bFreeModule && m_hModule )
|
||||
::FreeLibrary( m_hModule );
|
||||
m_eResult = SYSCALL_SUCCESS;
|
||||
m_hModule = NULL;
|
||||
m_pfnSysCall = NULL;
|
||||
m_bFreeModule = false;
|
||||
m_bInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CSysCallCacheEntry::SetFailed( SYSTEM_CALL_RESULT_t eResult )
|
||||
{
|
||||
m_eResult = eResult;
|
||||
}
|
||||
|
||||
template < typename FN >
|
||||
FN CSysCallCacheEntry::GetFunction() const
|
||||
{
|
||||
return reinterpret_cast< FN >( m_pfnSysCall );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Plat_GetMemPageSize
|
||||
// Returns the size of a memory page in bytes.
|
||||
//
|
||||
unsigned long Plat_GetMemPageSize()
|
||||
{
|
||||
return 4; // On 32-bit systems memory page size is 4 Kb
|
||||
}
|
||||
|
||||
//
|
||||
// Plat_GetPagedPoolInfo
|
||||
// Fills in the paged pool info structure if successful.
|
||||
//
|
||||
SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI )
|
||||
{
|
||||
memset( pPPI, 0, sizeof( *pPPI ) );
|
||||
|
||||
static CSysCallCacheEntry_FindModule qsi( _T( "ntdll.dll" ), "NtQuerySystemInformation" );
|
||||
|
||||
if ( qsi.CallResult() != SYSCALL_SUCCESS )
|
||||
return qsi.CallResult();
|
||||
|
||||
static bool s_bOsVersionValid = false;
|
||||
if ( !s_bOsVersionValid )
|
||||
{
|
||||
s_bOsVersionValid = true;
|
||||
OSVERSIONINFO osver;
|
||||
memset( &osver, 0, sizeof( osver ) );
|
||||
osver.dwOSVersionInfoSize = sizeof( osver );
|
||||
GetVersionEx( &osver );
|
||||
|
||||
// We should run it only on Windows XP or Windows 2003
|
||||
#define MAKEVER( high, low ) DWORD( MAKELONG( low, high ) )
|
||||
DWORD dwOsVer = MAKEVER( osver.dwMajorVersion, osver.dwMinorVersion );
|
||||
if ( dwOsVer < MAKEVER( 5, 1 ) || // Earlier than WinXP
|
||||
dwOsVer > MAKEVER( 5, 2 ) ) // Later than Win2003 (or 64-bit)
|
||||
{
|
||||
qsi.SetFailed( SYSCALL_UNSUPPORTED );
|
||||
}
|
||||
|
||||
// Don't care for 64-bit Windows
|
||||
CSysCallCacheEntry_FindModule wow64( _T( "kernel32.dll" ), "IsWow64Process" );
|
||||
if ( wow64.CallResult() == SYSCALL_SUCCESS )
|
||||
{
|
||||
typedef BOOL ( WINAPI * PFNWOW64 )( HANDLE, PBOOL );
|
||||
BOOL b64 = FALSE;
|
||||
if ( ( wow64.GetFunction< PFNWOW64 >() )( GetCurrentProcess(), &b64 ) &&
|
||||
b64 )
|
||||
{
|
||||
qsi.SetFailed( SYSCALL_UNSUPPORTED );
|
||||
}
|
||||
}
|
||||
|
||||
if ( qsi.CallResult() != SYSCALL_SUCCESS )
|
||||
return qsi.CallResult();
|
||||
}
|
||||
|
||||
// Invoke proc
|
||||
PrivateType( SYSTEM_PERFORMANCE_INFORMATION ) spi = {};
|
||||
ULONG ulLength = sizeof( spi );
|
||||
PrivateType( NTSTATUS ) lResult =
|
||||
( qsi.GetFunction< PrivateType( NtQuerySystemInformation ) >() )
|
||||
( SystemPerformanceInformation, &spi, ulLength, &ulLength );
|
||||
if ( lResult )
|
||||
return SYSCALL_FAILED;
|
||||
|
||||
// Return the result
|
||||
pPPI->numPagesUsed = spi.PagedPoolPages;
|
||||
pPPI->numPagesFree = spi.FreePagedPoolPages;
|
||||
return SYSCALL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
//
|
||||
// Plat_GetMemPageSize
|
||||
// Returns the size of a memory page in bytes.
|
||||
//
|
||||
unsigned long Plat_GetMemPageSize()
|
||||
{
|
||||
return 4; // Assume unknown page size is 4 Kb
|
||||
}
|
||||
|
||||
//
|
||||
// Plat_GetPagedPoolInfo
|
||||
// Fills in the paged pool info structure if successful.
|
||||
//
|
||||
SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI )
|
||||
{
|
||||
memset( pPPI, 0, sizeof( *pPPI ) );
|
||||
return SYSCALL_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user