windows核心编程 第14章,虚拟内存:获取系统信息
14,获取系统消息
14.1 系统信息
许多操作系统的值是根据主机而定的,比如页面的大小,分配粒度的大小等。这些值决不应该用硬编码的形式放入你的源代码。相反,你始终都应该在进程初始化的时候检索这些值并在你的源代码中使用检索到的值。GetSystemInfo函数将用于检索与主机相关的值:
VOID GetSystemInfo(LPSYSTEM_INFO psinf):
必须传递SYSTEM_INFO结构的地址给这个函数。这个函数将初始化所有的结构成员然后返回。下面是SYSTEM INFO数据结构的样子
typedef struct _SYSTEM_INFO {
union {
DWORD dwOemId; // Obsolete field...do not use
struct {
WORD wProcessorArchitecture;
WORD wReserved;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO, * LPSYSTEM_INFO;
当系统引导时,它要确定这些成员的值是什么。对于任何既定的系统来说,这些值总是相同的,因此决不需要为任何既定的进程多次调用该函数。由于有了GetSystemInfo函数,因此应用程序能够在运行的时候查询这些值。在该结构的所有成员中,只有4个成员与内存有关。表14-1对这4个成员作了描述。
/******************************************************************************
14_SysInfo.cpp
显示SYSTEM_INFO结构体信息
******************************************************************************/
#include "CmnHdr.h" /* See Appendix A. */
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h>
#include "Resource.h"
#include <StrSafe.h>
///
//将数据转换为字符,并用逗号分开
PTSTR BigNumToString(LONG lNum, PTSTR szBuf, DWORD chBufSize);
void ShowCPUInfo(HWND hWnd, WORD wProcessorArchitecture, WORD wProcessorLevel,
WORD wProcessorRevision);//显示CPU信息
void ShowBitness(HWND hWnd);//显示对话框标题
BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam);
void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify);
INT_PTR WINAPI Dlg_Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
///
int WINAPI _tWinMain(HINSTANCE hInstExe, HINSTANCE, PTSTR, int) {
DialogBox(hInstExe, MAKEINTRESOURCE(IDD_SYSINFO), NULL, Dlg_Proc);
return(0);
}
INT_PTR WINAPI Dlg_Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hDlg, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hDlg, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) {
chSETDLGICONS(hWnd, IDI_SYSINFO);
//获取系统信息
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
//显示CPU信息
ShowCPUInfo(hWnd, sinf.wProcessorArchitecture,
sinf.wProcessorLevel, sinf.wProcessorRevision);
//显示页面大小
TCHAR szBuf[50];
SetDlgItemText(hWnd, IDC_PAGESIZE,
BigNumToString(sinf.dwPageSize, szBuf, _countof(szBuf)));
//显示进程可用的最小地址
StringCchPrintf(szBuf, _countof(szBuf), TEXT("%p"),
sinf.lpMinimumApplicationAddress);
SetDlgItemText(hWnd, IDC_MINAPPADDR, szBuf);
//显示进程可用的最大地址
StringCchPrintf(szBuf, _countof(szBuf), TEXT("%p"),
sinf.lpMaximumApplicationAddress);
SetDlgItemText(hWnd, IDC_MAXAPPADDR, szBuf);
//显示CPU掩码
StringCchPrintf(szBuf, _countof(szBuf), TEXT("0x%016I64X"),
(__int64)sinf.dwActiveProcessorMask);
SetDlgItemText(hWnd, IDC_ACTIVEPROCMASK, szBuf);
//显示CPU核数
SetDlgItemText(hWnd, IDC_NUMOFPROCS,
BigNumToString(sinf.dwNumberOfProcessors, szBuf, _countof(szBuf)));
//分配颗粒度
SetDlgItemText(hWnd, IDC_ALLOCGRAN,
BigNumToString(sinf.dwAllocationGranularity, szBuf, _countof(szBuf)));
//显示对话框标题
ShowBitness(hWnd);
return(TRUE);
}
void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) {
switch (id) {
case IDCANCEL:
EndDialog(hWnd, id);
break;
}
}
//将数据转换为字符,并用逗号分开
PTSTR BigNumToString(LONG lNum, PTSTR szBuf, DWORD chBufSize) {
TCHAR szNum[100];
StringCchPrintf(szNum, _countof(szNum), TEXT("%d"), lNum);
NUMBERFMT nf;
nf.NumDigits = 0;//系数为数
nf.LeadingZero = FALSE;//是否添加前导0
nf.Grouping = 3;//每3位一组
nf.lpDecimalSep = (LPWSTR)TEXT(".");//指向以null结尾的小数分隔符字符串的指针
nf.lpThousandSep = (LPWSTR)TEXT(",");//指向以null结尾的千位分隔符字符串的指针
nf.NegativeOrder = 0;//负数模式
//将数字字符串格式化位标识符指定的语言环境定制的数字字符串
GetNumberFormat(LOCALE_USER_DEFAULT, 0, szNum, &nf, szBuf, chBufSize);
return(szBuf);
}
///
void ShowCPUInfo(HWND hWnd, WORD wProcessorArchitecture, WORD wProcessorLevel,
WORD wProcessorRevision) {
TCHAR szCPUArch[64] = TEXT("(未知)");
TCHAR szCPULevel[64] = TEXT("(未知)");
TCHAR szCPURev[64] = TEXT("(未知)");
switch (wProcessorArchitecture) {
// Notice that AMD processors are seen as PROCESSOR_ARCHITECTURE_INTEL.
// In the Registry, the content of the "VendorIdentifier" key under
// HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0
// is either "GenuineIntel" or "AuthenticAMD"
//
case PROCESSOR_ARCHITECTURE_INTEL: //x86
_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("Intel"));
switch (wProcessorLevel) {
case 3: case 4: //80386,80486
StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("80%c86"), wProcessorLevel + '0');
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("%c%d"),
HIBYTE(wProcessorRevision) + TEXT('A'),
LOBYTE(wProcessorRevision));
break;
case 5:
_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Pentium"));
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d, Stepping %d"),
HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision));
break;
case 6:
switch (HIBYTE(wProcessorRevision)) { // Model
case 1:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Pentium Pro"));
break;
case 3:
case 5:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Pentium II"));
break;
case 6:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Celeron"));
break;
case 7:
case 8:
case 11:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Pentium III"));
break;
case 9:
case 13:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Pentium M"));
break;
case 10:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Pentium Xeon"));
break;
case 15:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Core 2 Duo"));
break;
default:
_tcscpy_s(szCPULevel, _countof(szCPULevel),
TEXT("Unknown Pentium"));
break;
}
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d, Stepping %d"),
HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision));
break;
case 15:
_tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Pentium 4"));
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d, Stepping %d"),
HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision));
break;
}
break;
case PROCESSOR_ARCHITECTURE_IA64:
_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("IA-64"));
StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"), wProcessorLevel);
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c, Pass %d"),
HIBYTE(wProcessorRevision) + TEXT('A'),
LOBYTE(wProcessorRevision));
break;
case PROCESSOR_ARCHITECTURE_AMD64:
_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("AMD64"));
StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"), wProcessorLevel);
StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c, Pass %d"),
HIBYTE(wProcessorRevision) + TEXT('A'),
LOBYTE(wProcessorRevision));
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
_tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("Unknown"));
break;
}
SetDlgItemText(hWnd, IDC_PROCARCH, szCPUArch);
SetDlgItemText(hWnd, IDC_PROCLEVEL, szCPULevel);
SetDlgItemText(hWnd, IDC_PROCREV, szCPURev);
}
void ShowBitness(HWND hWnd) {
TCHAR szFullTitle[100];
TCHAR szTitle[32];
GetWindowText(hWnd, szTitle, _countof(szTitle));
#if defined(_WIN64)
//64位的应用程序只能运行在64位操作系统,这里不需要检查
StringCchPrintf(szFullTitle, _countof(szFullTitle),
TEXT("64-bit %s"), szTitle);
#else
BOOL bIsWow64 = FALSE;
//去顶指定的进程是在WOW64还是X64处理器的Intel64下运行
if (!IsWow64Process(GetCurrentProcess(), &bIsWow64)) {
chFAIL((PSTR)TEXT("Failed to get WOW64 state."));
return;
}
if (bIsWow64) {
StringCchPrintf(szFullTitle, _countof(szFullTitle),
TEXT("32-bit %s on WOW64"), szTitle);
} else {
StringCchPrintf(szFullTitle, _countof(szFullTitle),
TEXT("32-bit %s on 32-bit Windows"), szTitle);
}
#endif
SetWindowText(hWnd, szFullTitle);
}