良いタイトルが思いつかない日記ブログ

オンラインゲーム「マビノギ」/モリアンサーバにいるwrs3のブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書く事で広告が消せます。

C言語からWindowsのバージョンを判別する(Vistaまで)

ググったらVBとかC#のサンプルばかりで、
やっと見つけたと思ったら.NETのOperatingSystemクラスを使用とかね。
C/C++のもあるにはあるけど短かったり古い記事だったりする。
この話題人気ないのかな。。。

Windowsのバージョンをメッセージボックスで表示するプログラム。
COMとか使ってない。
BCC55、VS2005でコンパイルできる。

……関数部分だけで250行あるので、
最悪C言語のダメなコーディングの例としてもどうぞ。

/////////////////////////////////
// ↓main.c
// *コンパイル時のWindowsバージョン指定についてはWINVERマクロなどを参照
#include <tchar.h>
#include <windows.h>
#include <stdlib.h>

// bcc55では定義されてない定数(BCCでコンパイルするとき必須)
#if defined(__BORLANDC__)
# ifndef PROCESSOR_ARCHITECTURE_AMD64
# define PROCESSOR_ARCHITECTURE_AMD64 9
# endif
# ifndef VER_SUITE_PERSONAL
# define VER_SUITE_PERSONAL 0x00000200
# endif
# ifndef VER_SUITE_BLADE
# define VER_SUITE_BLADE 0x00000400
# endif
# ifndef VER_SUITE_STORAGE_SERVER
# define VER_SUITE_STORAGE_SERVER 0x00002000
# endif
# ifndef VER_SUITE_COMPUTE_SERVER
# define VER_SUITE_COMPUTE_SERVER 0x00004000
# endif
#endif


// [Windows Server 2003 R2]のSDKでは定義されてない定数
// (こちらもBCCでコンパイルするときは必須)
// 最新版SDKは*.iso(img)で配布されてるけど、サイズでかすぎてDLするのメンドい。
// * GetSystemMetrics()で使われる定数
#define SM_TABLETPC 86
#define SM_MEDIACENTER 87
#define SM_STARTER 88
#define SM_SERVERR2 89
// * GetProductInfo()で使われる定数
#define PRODUCT_UNLICENSED 0xABCDABCD
#define PRODUCT_BUSINESS 0x00000006 // Business Edition
#define PRODUCT_BUSINESS_N 0x00000010 // Business Edition
#define PRODUCT_CLUSTER_SERVER 0x00000012 // Cluster Server Edition
#define PRODUCT_DATACENTER_SERVER 0x00000008 // Server Datacenter Edition (full installation)
#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C // Server Datacenter Edition (core installation)
#define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027 // Server Datacenter Edition without Hyper-V (core installation)
#define PRODUCT_DATACENTER_SERVER_V 0x00000025 // Server Datacenter Edition without Hyper-V (full installation)
#define PRODUCT_ENTERPRISE 0x00000004 // Enterprise Edition
#define PRODUCT_ENTERPRISE_N 0x0000001B // Enterprise Edition
#define PRODUCT_ENTERPRISE_SERVER 0x0000000A // Server Enterprise Edition (full installation)
#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E // Server Enterprise Edition (core installation)
#define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029 // Server Enterprise Edition without Hyper-V (core installation)
#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F // Server Enterprise Edition for Itanium-based Systems
#define PRODUCT_ENTERPRISE_SERVER_V 0x00000026 // Server Enterprise Edition without Hyper-V (full installation)
#define PRODUCT_HOME_BASIC 0x00000002 // Home Basic Edition
#define PRODUCT_HOME_BASIC_N 0x00000005 // Home Basic Edition
#define PRODUCT_HOME_PREMIUM 0x00000003 // Home Premium Edition
#define PRODUCT_HOME_PREMIUM_N 0x0000001A // Home Premium Edition
#define PRODUCT_HOME_SERVER 0x00000013 // Home Server Edition
#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E // Windows Essential Business Server Management Server
#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020 // Windows Essential Business Server Messaging Server
#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F // Windows Essential Business Server Security Server
#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 // Server for Small Business Edition
#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 // Small Business Server
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 // Small Business Server Premium Edition
#define PRODUCT_STANDARD_SERVER 0x00000007 // Server Standard Edition (full installation)
#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D // Server Standard Edition (core installation)
#define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028 // Server Standard Edition without Hyper-V (core installation)
#define PRODUCT_STANDARD_SERVER_V 0x00000024 // Server Standard Edition without Hyper-V (full installation)
#define PRODUCT_STARTER 0x0000000B // Starter Edition
#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 // Storage Server Enterprise Edition
#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 // Storage Server Express Edition
#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 // Storage Server Standard Edition
#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 // Storage Server Workgroup Edition
#define PRODUCT_UNDEFINED 0x00000000 // An unknown product
#define PRODUCT_ULTIMATE 0x00000001 // Ultimate Edition
#define PRODUCT_ULTIMATE_N 0x0000001C // Ultimate Edition
#define PRODUCT_WEB_SERVER 0x00000011 // Web Server Edition (full installation)
#define PRODUCT_WEB_SERVER_CORE 0x0000001D // Web Server Edition (core installation)


#define BUFSIZE 256// 後の方でレジストリから値を読み出すときに使うバッファの大きさ
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);// GetNativeSystemInfo()
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);// GetProductInfo()

// [http://msdn2.microsoft.com/en-us/library/ms724429.aspx]より改変。
// ↑久々に見たら判別のサンプルプログラムが変わっててびっくりした。気のせいか?
/*
szOut: バージョンの文字列を格納するバッファ
bShowErrorBox: エラーのときメッセージボックスを表示するかどうか

szOutがNULLのとき確保すべきバッファのサイズが返る
szOutがNULLでないときバッファに格納された文字数が返る

保存される文字列の形式「Windows なんたら 〜 サービスパックx」
*/
int _GetWindowsVersionString(LPTSTR szOut, BOOL bShowErrorBox){
LPCTSTR s_os = TEXT("");
LPCTSTR s_os_sub1 = TEXT("");
LPCTSTR s_os_sub2 = TEXT("");
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
SYSTEM_INFO si;
PGNSI pGNSI;
PGPI pGPI;
DWORD dwType;

// 0クリア
ZeroMemory(&osvi, sizeof(osvi));
ZeroMemory(&si, sizeof(si));

// OSVERSIONINFOEXはWindows NT 4.0 SP6以降で使える。
// 関数が失敗したらOSVERSIONINFOを使う。
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if((bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi)) == 0){
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx((OSVERSIONINFO*)&osvi)){
if (bShowErrorBox)
MessageBox(NULL, TEXT("error: GetVersionEx(OSVERSIONINFO)"), TEXT("verify windows version"), MB_OK|MB_TOPMOST|MB_ICONEXCLAMATION);// ありえんと思うが...
return 0;
}
}
// GetNativeSystemInfo()はXP以降で使える。
// APIがなければGetSystemInfo()を使う。
pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");// GetModuleHandleで受けたハンドルはFreeLibraryしなくてイイ!
if(NULL != pGNSI){
pGNSI(&si);
}else{
GetSystemInfo(&si);
}

// (「Windows なんたら 〜 サービスパックx」の「Windows なんたら」の部分)
switch (osvi.dwPlatformId){
case VER_PLATFORM_WIN32s:
s_os = TEXT("Windows 3.1(Win32s)");
break;
case VER_PLATFORM_WIN32_WINDOWS:// →osvi.dwMajorVersion == 4のはず
switch (osvi.dwMinorVersion){
case 0:
s_os = TEXT("Windows 95");
break;
case 10:
s_os = TEXT("Windows 98");
break;
case 90:
s_os = TEXT("Windows Millennium Edition");
break;
default:
s_os = TEXT("Windows 9x");
break;
}
break;
case VER_PLATFORM_WIN32_NT:
switch (osvi.dwMajorVersion){
case 3:// →osvi.dwMinorVersion == 51のはず
s_os = TEXT("Windows NT 3.51");
break;
case 4:// →osvi.dwMinorVersion == 0のはず
s_os = TEXT("Windows NT 4.0");
break;
case 5:
switch (osvi.dwMinorVersion){
case 0:
s_os = TEXT("Windows 2000");
break;
case 1:
s_os = TEXT("Windows XP");
break;
case 2:
if (GetSystemMetrics(SM_SERVERR2) != 0){
s_os = TEXT("Windows Server 2003(R2)");
}else{
if (osvi.wSuiteMask == VER_SUITE_STORAGE_SERVER){
s_os = TEXT("Windows Storage Server 2003");
}else{
if (bOsVersionInfoEx){
if ((osvi.wProductType == VER_NT_WORKSTATION) && (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)){
s_os = TEXT("Windows XP Professional x64 Edition");
}else{
s_os = TEXT("Windows Server 2003");
}
break;
}
s_os = TEXT("Windows XP Professional x64 Edition or Windows Server 2003");
}
}
break;
}
break;
case 6:
if (bOsVersionInfoEx){
if (osvi.wProductType == VER_NT_WORKSTATION){
s_os = TEXT("Windows Vista");
}else{
s_os = TEXT("Windows Server 2008");
}
break;
}
s_os = TEXT("Windows Vista or Windows Server 2008");
break;
default:
s_os = TEXT("Windows NT");
break;
}
break;
default:
s_os = TEXT("(unknown OS)");
}

// さらに詳しく調べる(「Windows なんたら 〜 サービスパックx」の「〜」の部分)
pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");// GetProductInfo()はWindows Vista以降で使える
if (pGPI != NULL){
if (pGPI(6, 0, 0, 0, &dwType)){
switch (dwType){
case PRODUCT_ULTIMATE:
s_os_sub1 = TEXT("Ultimate Edition");
break;
case PRODUCT_HOME_PREMIUM:
s_os_sub1 = TEXT("Home Premium Edition");
break;
case PRODUCT_HOME_BASIC:
s_os_sub1 = TEXT("Home Basic Edition");
break;
case PRODUCT_ENTERPRISE:
s_os_sub1 = TEXT("Enterprise Edition");
break;
case PRODUCT_BUSINESS:
s_os_sub1 = TEXT("Business Edition");
break;
case PRODUCT_STARTER:
s_os_sub1 = TEXT("Starter Edition");
break;
case PRODUCT_CLUSTER_SERVER:
s_os_sub1 = TEXT("Cluster Server Edition");
break;
case PRODUCT_DATACENTER_SERVER:
s_os_sub1 = TEXT("Datacenter Edition");
break;
case PRODUCT_DATACENTER_SERVER_CORE:
s_os_sub1 = TEXT("Datacenter Edition (core installation)");
break;
case PRODUCT_ENTERPRISE_SERVER:
s_os_sub1 = TEXT("Enterprise Edition");
break;
case PRODUCT_ENTERPRISE_SERVER_CORE:
s_os_sub1 = TEXT("Enterprise Edition (core installation)");
break;
case PRODUCT_ENTERPRISE_SERVER_IA64:
s_os_sub1 = TEXT("Enterprise Edition for Itanium-based Systems");
break;
case PRODUCT_SMALLBUSINESS_SERVER:
s_os_sub1 = TEXT("Small Business Server");
break;
case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
s_os_sub1 = TEXT("Small Business Server Premium Edition");
break;
case PRODUCT_STANDARD_SERVER:
s_os_sub1 = TEXT("Standard Edition");
break;
case PRODUCT_STANDARD_SERVER_CORE:
s_os_sub1 = TEXT("Standard Edition (core installation)");
break;
case PRODUCT_WEB_SERVER:
s_os_sub1 = TEXT("Web Server Edition");
break;
case PRODUCT_UNLICENSED:
s_os_sub1 = TEXT("(unknown edition)");
if (bShowErrorBox)
MessageBox(NULL, TEXT("error: GetProductInfo() (had not been activated?)"), TEXT("verify windows version"), MB_OK|MB_TOPMOST|MB_ICONEXCLAMATION);// このエラーはあり得るので処理は続ける
break;
}
if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
s_os_sub2 = TEXT( ", 64-bit");
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
s_os_sub2 = TEXT(", 32-bit");
}
}
if (bOsVersionInfoEx){// ○Windows NT 4.0 SP6以降の製品の種類を判別
if ((osvi.wProductType == VER_NT_WORKSTATION) && (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_AMD64)){// ☆ワクステの種類を判別
if (osvi.dwMajorVersion == 4)
s_os_sub1 = TEXT(" Workstation 4.0");
// ↓ここから...
else if (GetSystemMetrics(SM_TABLETPC) != 0)
s_os = TEXT(" Tablet PC Edition");
else if (GetSystemMetrics(SM_MEDIACENTER) != 0)
s_os = TEXT(" Media Center Edition");
else if (GetSystemMetrics(SM_STARTER) != 0)
s_os = TEXT(" Starter Edition");
else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
s_os_sub1 = TEXT(" Home Edition");
else
s_os_sub1 = TEXT(" Professional");
// ↑ここまでがXPの種類判別。先に市場限定バージョンを区別している。
}else if ((osvi.wProductType == VER_NT_SERVER) || (osvi.wProductType == VER_NT_DOMAIN_CONTROLLER)){// ☆鯖の種類を判別
if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)){// Windows 2003 Server(or R2)
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64){
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
s_os_sub1 = TEXT(" Datacenter Edition for Itanium-based Systems");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
s_os_sub1 = TEXT(" Enterprise Edition for Itanium-based Systems");
}else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64){
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
s_os_sub1 = TEXT(" Datacenter x64 Edition");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
s_os_sub1 = TEXT(" Enterprise x64 Edition");
else
s_os_sub1 = TEXT(" Standard x64 Edition");
}else{
if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
s_os_sub1 = TEXT(" Compute Cluster Edition");
else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
s_os_sub1 = TEXT(" Datacenter Edition");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
s_os_sub1 = TEXT(" Enterprise Edition");
else if (osvi.wSuiteMask & VER_SUITE_BLADE)
s_os_sub1 = TEXT(" Web Edition");
else
s_os_sub1 = TEXT(" Standard Edition");
}
}else if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)){// Windows 2000
if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
s_os_sub1 = TEXT(" Datacenter Server");
else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
s_os_sub1 = TEXT(" Advanced Server");
else
s_os_sub1 = TEXT(" Server");
}else{// Windows NT 4.0
if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
s_os_sub1 = TEXT(" Server 4.0, Enterprise Edition");
else
s_os_sub1 = TEXT(" Server 4.0");
}
}
}else{// ○Windows NT 4.0 SP5以前の製品の種類を判別
HKEY hKey;
TCHAR szProductType[BUFSIZE] = TEXT("");
DWORD dwBufLen = BUFSIZE * sizeof(TCHAR);
LONG lRet;

lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hKey);
if (lRet != ERROR_SUCCESS){
if (bShowErrorBox)
MessageBox(NULL, TEXT("error: RegOpenKeyEx(OSVERSIONINFO)"), TEXT("verify windows version"), MB_OK|MB_TOPMOST|MB_ICONEXCLAMATION);// ありえんと思うが...
return 0;
}

lRet = RegQueryValueEx(hKey, TEXT("ProductType"), NULL, NULL, (LPBYTE)szProductType, &dwBufLen);
RegCloseKey(hKey);

if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE * sizeof(TCHAR))){
if (bShowErrorBox)
MessageBox(NULL, TEXT("error: RegQueryValueEx()"), TEXT("verify windows version"), MB_OK|MB_TOPMOST|MB_ICONEXCLAMATION);// ありえんと思うが...
return 0;
}

if (lstrcmpi(TEXT("WINNT"), szProductType) == 0) s_os_sub1 = TEXT(" Workstation");
if (lstrcmpi(TEXT("LANMANNT"), szProductType) == 0) s_os_sub1 = TEXT(" Server");
if (lstrcmpi(TEXT("SERVERNT"), szProductType) == 0) s_os_sub1 = TEXT(" Advanced Server");
}

if (szOut == NULL){
return lstrlen(s_os) + lstrlen(s_os_sub1) + lstrlen(s_os_sub2) + lstrlen(TEXT(" "))/*空白の分*/ + lstrlen(osvi.szCSDVersion) + lstrlen(TEXT("\0"));
}
return wsprintf(szOut, TEXT("%s%s%s %s"), s_os, s_os_sub1, s_os_sub2, osvi.szCSDVersion);
}

int _tmain(){
int nBufSize;
LPTSTR pBuf;

nBufSize = _GetWindowsVersionString(NULL, FALSE);
pBuf = (LPTSTR)calloc(nBufSize, 1);
_GetWindowsVersionString(pBuf, FALSE);
MessageBox(NULL, pBuf, TEXT("test"), MB_OK);
free(pBuf);

return 0;
}
// ↑main.c
/////////////////////////////////

もしこれを読んで興味がある人がいたら試して欲しいと思う。
WindowsXP(Home Edition)とWindows2k(Service Pack 4)でしか実験できてなくて、
間違いがあったら修正したい。

テーマ:プログラミング - ジャンル:コンピュータ

<<0x00B9日目 | HOME | C言語からOleLoadPicture関数を使う>>

コメント

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2011/12/05(月) 04:01:07 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2011/12/13(火) 01:39:24 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2011/12/15(木) 16:20:16 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2012/01/15(日) 01:11:55 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2012/01/23(月) 14:20:06 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2012/02/01(水) 02:39:41 |
  2. |
  3. #
  4. [ 編集]

承認待ちコメント

このコメントは管理者の承認待ちです
  1. 2012/02/05(日) 13:58:48 |
  2. |
  3. #
  4. [ 編集]

コメントの投稿

管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://yandyle.blog121.fc2.com/tb.php/174-cab5317e
この記事にトラックバックする(FC2ブログユーザー)

C言語 (Win32) から Windows のバージョンを判別する (Windows 7 対応しかけ)

ちょっと必要があり C 言語から Windows の製品バージョン、エディションを取得する方法を調べた。 簡単かと思いきや、一発で取得できるような API はなく、バージョン毎にエディションを調べる方法が多様でなかなか面倒だった。 MSDN の Getting the System Version (Win...
  1. 2009/06/28(日) 16:10:57 |
  2. [ぴ]