Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
7.3 KiB

  1. //====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "pch_tier0.h"
  9. #ifdef PLATFORM_WINDOWS_PC
  10. #include "tier0/valve_off.h"
  11. #include <windows.h>
  12. #include <tchar.h>
  13. #include "tier0/valve_on.h"
  14. #endif
  15. #include "tier0/platform.h"
  16. #include "tier0/systeminformation.h"
  17. // NOTE: This has to be the last file included!
  18. #include "tier0/memdbgon.h"
  19. #ifdef PLATFORM_WINDOWS_PC
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. #define PrivateType( xxx ) ValvePrivateType_##xxx
  24. typedef enum { SystemPerformanceInformation = 2 }
  25. PrivateType( SYSTEM_INFORMATION_CLASS );
  26. typedef LONG PrivateType( NTSTATUS );
  27. typedef PrivateType( NTSTATUS ) ( WINAPI * PrivateType( NtQuerySystemInformation ) )
  28. (
  29. /*IN*/ PrivateType( SYSTEM_INFORMATION_CLASS ) SystemInformationClass,
  30. /*OUT*/ PVOID SystemInformation,
  31. /*IN*/ ULONG SystemInformationLength,
  32. /*OUT*/ PULONG ReturnLength /*OPTIONAL*/
  33. );
  34. typedef struct
  35. {
  36. LARGE_INTEGER IdleProcessTime;
  37. LARGE_INTEGER IoTransferCount[3];
  38. ULONG IoOperationCount[3];
  39. ULONG AvailablePages;
  40. ULONG CommittedPages;
  41. ULONG CommitLimit;
  42. ULONG u00683;
  43. ULONG u00684;
  44. ULONG u00685;
  45. ULONG u00686;
  46. ULONG u00687;
  47. ULONG u00688;
  48. ULONG u00689;
  49. ULONG u00690;
  50. ULONG u00691;
  51. ULONG u00692;
  52. ULONG u00693;
  53. ULONG u00694;
  54. ULONG u00695;
  55. ULONG u00696;
  56. ULONG PagedPoolPages;
  57. ULONG NonPagedPoolPages;
  58. ULONG PagedPoolAllocs;
  59. ULONG PagedPoolFrees;
  60. ULONG NonPagedPoolAllocs;
  61. ULONG NonPagedPoolFrees;
  62. ULONG FreeSystemPtes;
  63. ULONG u00704;
  64. ULONG u00705;
  65. ULONG u00706;
  66. ULONG NonPagedPoolLookasideHits;
  67. ULONG PagedPoolLookasideHits;
  68. ULONG FreePagedPoolPages;
  69. ULONG u00710;
  70. ULONG u00711;
  71. ULONG u00712;
  72. ULONG uCounters[34];
  73. }
  74. PrivateType( SYSTEM_PERFORMANCE_INFORMATION );
  75. #ifdef __cplusplus
  76. }
  77. #endif
  78. //
  79. // Cached information about a dll proc
  80. //
  81. class CSysCallCacheEntry
  82. {
  83. public:
  84. CSysCallCacheEntry();
  85. ~CSysCallCacheEntry();
  86. public:
  87. bool IsInitialized() const;
  88. SYSTEM_CALL_RESULT_t CallResult() const;
  89. SYSTEM_CALL_RESULT_t InitializeLoadModule( _TCHAR *pszModule, char *pszFunction );
  90. SYSTEM_CALL_RESULT_t InitializeFindModule( _TCHAR *pszModule, char *pszFunction );
  91. SYSTEM_CALL_RESULT_t InitializeFindProc( HMODULE hModule, char *pszFunction );
  92. void SetFailed( SYSTEM_CALL_RESULT_t eResult );
  93. void Reset();
  94. template < typename FN >
  95. FN GetFunction() const;
  96. protected:
  97. SYSTEM_CALL_RESULT_t m_eResult;
  98. FARPROC m_pfnSysCall;
  99. HMODULE m_hModule;
  100. bool m_bInitialized;
  101. bool m_bFreeModule;
  102. };
  103. struct CSysCallCacheEntry_LoadModule : public CSysCallCacheEntry
  104. {
  105. CSysCallCacheEntry_LoadModule( _TCHAR *pszModule, char *pszFunction ) { InitializeLoadModule( pszModule, pszFunction ); }
  106. };
  107. struct CSysCallCacheEntry_FindModule : public CSysCallCacheEntry
  108. {
  109. CSysCallCacheEntry_FindModule( _TCHAR *pszModule, char *pszFunction ) { InitializeFindModule( pszModule, pszFunction ); }
  110. };
  111. struct CSysCallCacheEntry_FindProc : public CSysCallCacheEntry
  112. {
  113. CSysCallCacheEntry_FindProc( HMODULE hModule, char *pszFunction ) { InitializeFindProc( hModule, pszFunction ); }
  114. };
  115. CSysCallCacheEntry::CSysCallCacheEntry() :
  116. m_eResult( SYSCALL_SUCCESS ),
  117. m_pfnSysCall( NULL ),
  118. m_hModule( NULL ),
  119. m_bInitialized( false ),
  120. m_bFreeModule( false )
  121. {
  122. NULL;
  123. }
  124. CSysCallCacheEntry::~CSysCallCacheEntry()
  125. {
  126. Reset();
  127. }
  128. bool CSysCallCacheEntry::IsInitialized() const
  129. {
  130. return m_bInitialized;
  131. }
  132. SYSTEM_CALL_RESULT_t CSysCallCacheEntry::CallResult() const
  133. {
  134. return m_eResult;
  135. }
  136. SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeLoadModule( _TCHAR *pszModule, char *pszFunction )
  137. {
  138. m_bInitialized = true;
  139. m_hModule = ::LoadLibrary( pszModule );
  140. m_bFreeModule = true;
  141. if ( !m_hModule )
  142. return m_eResult = SYSCALL_NODLL;
  143. return InitializeFindProc( m_hModule, pszFunction );
  144. }
  145. SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeFindModule( _TCHAR *pszModule, char *pszFunction )
  146. {
  147. m_bInitialized = true;
  148. m_hModule = ::GetModuleHandle( pszModule );
  149. m_bFreeModule = false;
  150. if ( !m_hModule )
  151. return m_eResult = SYSCALL_NODLL;
  152. return InitializeFindProc( m_hModule, pszFunction );
  153. }
  154. SYSTEM_CALL_RESULT_t CSysCallCacheEntry::InitializeFindProc( HMODULE hModule, char *pszFunction )
  155. {
  156. m_bInitialized = true;
  157. m_pfnSysCall = GetProcAddress( hModule, pszFunction );
  158. if ( !m_pfnSysCall )
  159. return m_eResult = SYSCALL_NOPROC;
  160. return m_eResult = SYSCALL_SUCCESS;
  161. }
  162. void CSysCallCacheEntry::Reset()
  163. {
  164. if ( m_bInitialized )
  165. {
  166. if ( m_bFreeModule && m_hModule )
  167. ::FreeLibrary( m_hModule );
  168. m_eResult = SYSCALL_SUCCESS;
  169. m_hModule = NULL;
  170. m_pfnSysCall = NULL;
  171. m_bFreeModule = false;
  172. m_bInitialized = false;
  173. }
  174. }
  175. void CSysCallCacheEntry::SetFailed( SYSTEM_CALL_RESULT_t eResult )
  176. {
  177. m_eResult = eResult;
  178. }
  179. template < typename FN >
  180. FN CSysCallCacheEntry::GetFunction() const
  181. {
  182. return reinterpret_cast< FN >( m_pfnSysCall );
  183. }
  184. //
  185. // Plat_GetMemPageSize
  186. // Returns the size of a memory page in bytes.
  187. //
  188. uint32 Plat_GetMemPageSize()
  189. {
  190. return 4; // On 32-bit systems memory page size is 4 Kb
  191. }
  192. //
  193. // Plat_GetPagedPoolInfo
  194. // Fills in the paged pool info structure if successful.
  195. //
  196. SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI )
  197. {
  198. memset( pPPI, 0, sizeof( *pPPI ) );
  199. static CSysCallCacheEntry_FindModule qsi( _T( "ntdll.dll" ), "NtQuerySystemInformation" );
  200. if ( qsi.CallResult() != SYSCALL_SUCCESS )
  201. return qsi.CallResult();
  202. static bool s_bOsVersionValid = false;
  203. if ( !s_bOsVersionValid )
  204. {
  205. s_bOsVersionValid = true;
  206. OSVERSIONINFO osver;
  207. memset( &osver, 0, sizeof( osver ) );
  208. osver.dwOSVersionInfoSize = sizeof( osver );
  209. GetVersionEx( &osver );
  210. // We should run it only on Windows XP or Windows 2003
  211. #define MAKEVER( high, low ) DWORD( MAKELONG( low, high ) )
  212. DWORD dwOsVer = MAKEVER( osver.dwMajorVersion, osver.dwMinorVersion );
  213. if ( dwOsVer < MAKEVER( 5, 1 ) || // Earlier than WinXP
  214. dwOsVer > MAKEVER( 5, 2 ) ) // Later than Win2003 (or 64-bit)
  215. {
  216. qsi.SetFailed( SYSCALL_UNSUPPORTED );
  217. }
  218. // Don't care for 64-bit Windows
  219. CSysCallCacheEntry_FindModule wow64( _T( "kernel32.dll" ), "IsWow64Process" );
  220. if ( wow64.CallResult() == SYSCALL_SUCCESS )
  221. {
  222. typedef BOOL ( WINAPI * PFNWOW64 )( HANDLE, PBOOL );
  223. BOOL b64 = FALSE;
  224. if ( ( wow64.GetFunction< PFNWOW64 >() )( GetCurrentProcess(), &b64 ) &&
  225. b64 )
  226. {
  227. qsi.SetFailed( SYSCALL_UNSUPPORTED );
  228. }
  229. }
  230. if ( qsi.CallResult() != SYSCALL_SUCCESS )
  231. return qsi.CallResult();
  232. }
  233. // Invoke proc
  234. PrivateType( SYSTEM_PERFORMANCE_INFORMATION ) spi;
  235. ULONG ulLength = sizeof( spi );
  236. PrivateType( NTSTATUS ) lResult =
  237. ( qsi.GetFunction< PrivateType( NtQuerySystemInformation ) >() )
  238. ( SystemPerformanceInformation, &spi, ulLength, &ulLength );
  239. if ( lResult )
  240. return SYSCALL_FAILED;
  241. // Return the result
  242. pPPI->numPagesUsed = spi.PagedPoolPages;
  243. pPPI->numPagesFree = spi.FreePagedPoolPages;
  244. return SYSCALL_SUCCESS;
  245. }
  246. #else
  247. //
  248. // Plat_GetMemPageSize
  249. // Returns the size of a memory page in bytes.
  250. //
  251. uint32 Plat_GetMemPageSize()
  252. {
  253. return 4; // Assume unknown page size is 4 Kb
  254. }
  255. //
  256. // Plat_GetPagedPoolInfo
  257. // Fills in the paged pool info structure if successful.
  258. //
  259. SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI )
  260. {
  261. memset( pPPI, 0, sizeof( *pPPI ) );
  262. return SYSCALL_UNSUPPORTED;
  263. }
  264. #endif