summaryrefslogtreecommitdiff
path: root/tier0/systeminformation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tier0/systeminformation.cpp')
-rw-r--r--tier0/systeminformation.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/tier0/systeminformation.cpp b/tier0/systeminformation.cpp
new file mode 100644
index 0000000..c26a2d1
--- /dev/null
+++ b/tier0/systeminformation.cpp
@@ -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 \ No newline at end of file