-
Notifications
You must be signed in to change notification settings - Fork 270
/
Copy pathsysteminformation.cpp
310 lines (257 loc) · 7.09 KB
/
systeminformation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
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