サンプル・プログラム
解説:CPU情報ファイル
0033: //CPU情報ファイル : オンライン
0034: define('PAHOO_PROCESSOR_LIST', 'https://www.pahoo.org/db/xml/processorList.xml');
0035: //CPU情報ファイル : ローカル
0036: define('LOCAL_PROCESSOR_LIST', 'processorList.xml');
これは、当サイトにある最新ファイルを参照するようにしているが、オンライン接続できない場合はローカルにあるファイルを参照するようにしている。
プログラムを実行すると、ウィンドウの右下に "(online:2018/01/25)" と表示されていたら、オンラインで当サイトの2018年(平成30年)1月25日の情報ファイルを読み込んでいることを示す。
"(local:2018/01/21)" ならば、ローカルにある2018年(平成30年)1月21日の情報ファイルを読み込んでいる。
"*error*" だと、CPU情報ファイルが見つからないことを意味する。
もし最新CPUをお持ちで正しい情報が表示されないようだったら、投稿コーナーへメッセージをお願いしたい。
解説:NativeSystemInfo Function
0165: /**
0166: * NativeSystemInfoを取得
0167: * @param array $sysinfo NativeSystemInfoを格納する配列
0168: * @return bool TRUE:取得成功/FALSE:失敗
0169: */
0170: function GetNativeSystemInfo(&$sysinfo) {
0171: //GetNativeSystemInfo function : msdn
0172: //https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms724340(v=vs.85).aspx
0173:
0174: //SYSTEM_INFO structure : msdn
0175: //https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms724958(v=vs.85).aspx
0176: define('SYSTEM_INFO', 'VdwOemId/VdwPageSize/VlpMinimumApplicationAddress/VlpMaximumApplicationAddress/VdwActiveProcessorMask/VdwNumberOfProcessors/VdwProcessorType/VdwAllocationGranularity/vwProcessorLevel/vwProcessorRevision');
0177: define('SYSTEM_INFO_RAW', "V8v2");
0178: define('SYSTEM_INFO_SIZE', 8 * 4 + 2 * 2);
0179:
0180: static $Kernel = NULL;
0181: static $GetNativeSystemInfo = NULL;
0182:
0183: //Kernel32.dll
0184: if ($Kernel == NULL) {
0185: $Kernel = wb_load_library('Kernel');
0186: }
0187: if ($Kernel == NULL) return FALSE;
0188:
0189: //GetNativeSystemInfo function
0190: if ($GetNativeSystemInfo == NULL) {
0191: $GetNativeSystemInfo = wb_get_function_address('GetNativeSystemInfo', $Kernel);
0192: }
0193: if ($GetNativeSystemInfo == NULL) return FALSE;
0194:
0195: $val = pack(SYSTEM_INFO_RAW, SYSTEM_INFO_SIZE, 0,0,0,0,0,0,0,0,0);
0196: wb_call_function($GetNativeSystemInfo, array($val));
0197: $arr = unpack(SYSTEM_INFO, $val);
0198: if (!isset($arr['dwOemId'])) return FALSE;
0199:
0200: //データの複写
0201: foreach ($arr as $key=>$val) $sysinfo[$key] = $val;
0202: return TRUE;
0203: }
このAPIは引数なしで、CPU情報を格納した構造体 SYSTEM_INFO を返す。SYSTEM_INFO の構造は、SYSTEM_INFO structure の通りである。
Win32API では、構造体がバイナリデータとして渡されるので、あらかじめ pack を使って構造体 SYSTEM_INFO を変数 $val に定義しておく。
wb_call_function を使って GetNativeSystemInfo を呼び出したら、今度は unpack を使い、構造体を配列 $arr に展開する。あらかじめ文字列 SYSTEM_INFO を用意しておくことで、受け取ったバイナリデータを構造体の形に合わせて連想配列に格納していく。
解説:CPU情報リストを取得する
0205: /**
0206: * CPU情報リストを取得する
0207: * @param array $processorList CPU情報リストを格納する配列
0208: * @return int 2:オンラインから取得,1:ローカルから取得,0:取得失敗
0209: */
0210: function getProcessorList(&$processorList) {
0211: $res = 0;
0212:
0213: //XML読み込み
0214: $options = array('parseAttributes' => TRUE);
0215: $xml = new XML_Unserializer($options);
0216:
0217: //CPU情報リスト : pahoo.org
0218: $xml_data = @file_get_contents(PAHOO_PROCESSOR_LIST);
0219: if ($xml_data) {
0220: $xml->unserialize($xml_data, FALSE);
0221: $processorList = $xml->getUnserializedData();
0222: $res = 2;
0223: //CPU情報リスト : ローカル
0224: } else {
0225: $xml_data = @file_get_contents(LOCAL_PROCESSOR_LIST);
0226: if ($xml_data) {
0227: $xml->unserialize($xml_data, FALSE);
0228: $processorList = $xml->getUnserializedData();
0229: $res = 1;
0230: }
0231: }
0232: unset($xml);
0233:
0234: //レスポンス・チェック
0235: if (! isset($processorList['processor'])) $res = 0;
0236:
0237: return $res;
0238: }
解説:CPU情報を取得
0240: /**
0241: * NativeSystemInfoの結果とCPU情報リストをマッチングしCPU情報を取得
0242: * @param array $sysinfo NativeSystemInfo
0243: * @param array $processorList CPU情報リスト
0244: * @param array $items CPU情報を格納する配列
0245: * @return bool TRUE:取得成功/FALSE:取得失敗
0246: */
0247: function getProcessorInfo($sysinfo, $processorList, &$items) {
0248: $items['level'] = (int)$sysinfo['wProcessorLevel'];
0249: $items['type'] = (int)$sysinfo['dwProcessorType'];
0250: $items['number'] = (int)$sysinfo['dwNumberOfProcessors'];
0251: $items['model'] = (int)$sysinfo['wProcessorRevision'] >> 8;
0252: $items['stepping'] = (int)$sysinfo['wProcessorRevision'] & 0x00FF;
0253: $items['vendor'] = 'unknown';
0254: $items['architecture'] = 'unknown';
0255:
0256: //マッチング
0257: foreach ($processorList['processor'] as $processor) {
0258: if (($items['level'] == hexdec($processor['family'])) && ($items['model'] == hexdec($processor['model']))) {
0259: $items['vendor'] = $processor['vendor'];
0260: $items['architecture'] = $processor['architecture'];
0261: break;
0262: }
0263: }
0264: }
その他、クリップボードへのコピー機能は、「PHPでクリップボードにテキスト貼り付け(Windowsアプリ版)」で紹介したプログラムを流用している。
コンパイル
なお、ダウンロードした圧縮ファイルを解凍すると、"cpuid.exe" のあるフォルダに "getProcessorList.xml" が解凍される。これがCPU情報リストで、内容を編集することで最新CPUの情報も正しく表示できるようになる。
参考サイト
- x86 ファミリーとモデル一覧:a4lg.com
Microsoftなどベンダ各社は、この脆弱性へのprovisionパッチを公開しているが、厄介なことに、CPUの世代によっては、動作が遅くなったり、再起動してしまう現象が報告されている。
そこで今回は、どの世代のCPUなのか、情報を取得・表示するWindowsアプリを作ってみることにする。
(2021年1月23日)CPU情報リストを更新