スペースモラトリアムノカミサマ

日記+コメント付きブックマーク+他人にも役に立つかもしれない情報など。
(更新情報: RSS(ツッコミ付き) / RSS(ツッコミ抜き) / LIRS)

最近の TrackBack:
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|06|07|08|09|10|
2011|01|02|03|07|10|11|
2012|02|03|04|07|08|09|
2013|01|06|07|
2014|02|08|09|11|
2015|09|
2016|01|05|
2017|07|
2018|05|07|
2019|07|
2020|08|09|10|12|
2021|05|
2022|03|

2009/06/27

_ [プログラミング] C言語 (Win32) から Windows のバージョンを判別する (Windows 7 対応しかけ)

ちょっと必要があり C 言語から Windows の製品バージョン、エディションを取得する方法を調べた。

簡単かと思いきや、一発で取得できるような API はなく、バージョン毎にエディションを調べる方法が多様でなかなか面倒だった。

MSDN の Getting the System Version (Windows) に公式なサンプルが載っているのだが、Windows 2000 以降にしか対応していない。

C言語からWindowsのバージョンを判別する(Vistaまで) はそれをベースに改良されていていい線行っているのだが、

  • Windows 95 OSR や Windows 98 Second Edition を区別できない
  • 最近の Windows Server のエディションに対応していない

という課題があったため、2つを参考に作った改良版が下記のサンプルだ。

Windows 95、NT 3.51 から、最近リリースされた Windows Server 2008 Foundation まで対応している。(…つもりだが、検証環境がないので本当に対応できているかどうかはわからない) また、Windows 7 や 2008 R2 にもある程度対応しているが、特に 2008 R2 はエディション名がよくわからず対応しきれていない。

各種定数は Microsoft Windows 7 SDK: RC から拝借した。

Windows Server 2008 のエディションの多さは異常…。

// OS のバージョン判別 (Windows 7 あたりまで対応)
// Getting the System Version (Windows)
// http://msdn2.microsoft.com/en-us/library/ms724429.aspx
// C言語から Windows のバージョンを判別する (Vistaまで)
// http://yandyle.blog121.fc2.com/blog-entry-174.html
// を参考に改良
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <strsafe.h>
 
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "advapi32.lib")
 
// GetVersionEx() で使われる定数 (VC++2005 未定義)
#define VER_SUITE_WH_SERVER 0x00008000
 
// GetSystemMetrics() で使われる定数 (VC++2005 未定義)
#define SM_TABLETPC     86
#define SM_MEDIACENTER  87
#define SM_STARTER      88
#define SM_SERVERR2     89
 
// GetProductInfo() で使われる定数 (VC++2005 未定義)
#define PRODUCT_UNDEFINED                           0x00000000 // An unknown product
#define PRODUCT_ULTIMATE                            0x00000001 // Ultimate Edition
#define PRODUCT_HOME_BASIC                          0x00000002 // Home Basic Edition
#define PRODUCT_HOME_PREMIUM                        0x00000003 // Home Premium Edition
#define PRODUCT_ENTERPRISE                          0x00000004 // Enterprise Edition
#define PRODUCT_HOME_BASIC_N                        0x00000005 // Home Basic Edition
#define PRODUCT_BUSINESS                            0x00000006 // Business Edition
#define PRODUCT_STANDARD_SERVER                     0x00000007 // Server Standard Edition
#define PRODUCT_DATACENTER_SERVER                   0x00000008 // Server Datacenter Edition
#define PRODUCT_SMALLBUSINESS_SERVER                0x00000009 // Small Business Server
#define PRODUCT_ENTERPRISE_SERVER                   0x0000000A // Server Enterprise Edition
#define PRODUCT_STARTER                             0x0000000B // Starter Edition
#define PRODUCT_DATACENTER_SERVER_CORE              0x0000000C // Server Datacenter Edition (core installation)
#define PRODUCT_STANDARD_SERVER_CORE                0x0000000D // Server Standard Edition (core installation)
#define PRODUCT_ENTERPRISE_SERVER_CORE              0x0000000E // Server Enterprise Edition (core installation)
#define PRODUCT_ENTERPRISE_SERVER_IA64              0x0000000F // Server Enterprise Edition for Itanium-based Systems
#define PRODUCT_BUSINESS_N                          0x00000010 // Business Edition
#define PRODUCT_WEB_SERVER                          0x00000011 // Web Server Edition
#define PRODUCT_CLUSTER_SERVER                      0x00000012 // Cluster Server Edition
#define PRODUCT_HOME_SERVER                         0x00000013 // Home Server 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_STORAGE_ENTERPRISE_SERVER           0x00000017 // Storage Server Enterprise Edition
#define PRODUCT_SERVER_FOR_SMALLBUSINESS            0x00000018 // Server for Small Business Edition
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM        0x00000019 // Small Business Server Premium Edition
#define PRODUCT_HOME_PREMIUM_N                      0x0000001A // Home Premium Edition
#define PRODUCT_ENTERPRISE_N                        0x0000001B // Enterprise Edition
#define PRODUCT_ULTIMATE_N                          0x0000001C // Ultimate Edition
#define PRODUCT_WEB_SERVER_CORE                     0x0000001D // Web Server Edition (core installation)
#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT    0x0000001E // Windows Essential Business Server Management Server
#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY      0x0000001F // Windows Essential Business Server Security Server
#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING     0x00000020 // Windows Essential Business Server Messaging Server
#define PRODUCT_SMALLBUSINESS_SERVER_PRIME          0x00000021 // Server Foundation
#define PRODUCT_HOME_PREMIUM_SERVER                 0x00000022 // Home Premium Server Edition?
#define PRODUCT_SERVER_FOR_SMALLBUSINESS_V          0x00000023 // Server 2008 without Hyper-V for Windows Essential Server Solutions
#define PRODUCT_STANDARD_SERVER_V                   0x00000024 // Server Standard Edition without Hyper-V
#define PRODUCT_DATACENTER_SERVER_V                 0x00000025 // Server Datacenter Edition without Hyper-V
#define PRODUCT_ENTERPRISE_SERVER_V                 0x00000026 // Server Enterprise Edition without Hyper-V
#define PRODUCT_DATACENTER_SERVER_CORE_V            0x00000027 // Server Datacenter Edition without Hyper-V (core installation)
#define PRODUCT_STANDARD_SERVER_CORE_V              0x00000028 // Server Standard Edition without Hyper-V (core installation)
#define PRODUCT_ENTERPRISE_SERVER_CORE_V            0x00000029 // Server Enterprise Edition without Hyper-V (core installation)
#define PRODUCT_HYPERV                              0x0000002A // Microsoft Hyper-V Server
#define PRODUCT_STORAGE_EXPRESS_SERVER_CORE         0x0000002B // Storage Server Express Edition (core installation)
#define PRODUCT_STORAGE_STANDARD_SERVER_CORE        0x0000002C // Storage Server Standard Edition (core installation)
#define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE       0x0000002D // Storage Server Workgroup Edition (core installation)
#define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE      0x0000002E // Storage Server Enterprise Edition (core installation)
#define PRODUCT_STARTER_N                           0x0000002F // Starter Edition
#define PRODUCT_PROFESSIONAL                        0x00000030 // Professional Edition
#define PRODUCT_PROFESSIONAL_N                      0x00000031 // Professional Edition
#define PRODUCT_SB_SOLUTION_SERVER                  0x00000032
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS             0x00000033
#define PRODUCT_STANDARD_SERVER_SOLUTIONS           0x00000034
#define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE      0x00000035 // (core installation)
#define PRODUCT_SB_SOLUTION_SERVER_EM               0x00000036
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM          0x00000037
#define PRODUCT_SOLUTION_EMBEDDEDSERVER             0x00000038
#define PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE        0x00000039 // (core installation)
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE   0x0000003F // (core installation)
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT       0x0000003B
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL       0x0000003C
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC    0x0000003D
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC    0x0000003E
#define PRODUCT_CLUSTER_SERVER_V                    0x00000040 // Cluster Server Edition without Hyper-V
#define PRODUCT_EMBEDDED                            0x00000041
#define PRODUCT_UNLICENSED                          0xABCDABCD
 
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
 
BOOL GetOSDisplayString(LPTSTR pszOS, size_t bufsize)
{
  // GetVersionEx による基礎判別
  OSVERSIONINFOEX osvi;
  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); // 必要あるのか?
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  BOOL bOsVersionInfoEx;
  if ((bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*)&osvi)) == FALSE) {
    // Windows NT 4.0 SP5 以前と Windows 9x
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx((OSVERSIONINFO *)&osvi)) return FALSE;
  }
 
  // Windows XP 以降では GetNativeSystemInfo を、それ以外では GetSystemInfo を使う
  SYSTEM_INFO si;
  ZeroMemory(&si, sizeof(SYSTEM_INFO)); // 必要あるのか?
  PGNSI pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
  if (pGNSI) pGNSI(&si);
  else GetSystemInfo(&si);
 
  // ここからバージョン別
  StringCchCopy(pszOS, bufsize, TEXT("")); // 念のため
  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 3) { // NT 系
 
    // Vista / 2008 / 7 / 2008 R2
    if (osvi.dwMajorVersion == 6) {
      TCHAR MajVerStr[9] = TEXT(""); // " 2008" か " 2008 R2" を入れる
      if (osvi.wProductType == VER_NT_WORKSTATION) { // Vista / 7
        if (osvi.dwMinorVersion == 0)
          StringCchCopy(pszOS, bufsize, TEXT("Windows Vista "));
        else if (osvi.dwMinorVersion == 1)
          StringCchCopy(pszOS, bufsize, TEXT("Windows 7 "));
        else
          StringCchCopy(pszOS, bufsize, TEXT("Windows NT 6.x(unknown) "));
      }
      else { // Server 2008 / R2
        StringCchCopy(pszOS, bufsize, TEXT("Windows Server"));
        if (osvi.dwMinorVersion == 0)
          StringCchCopy(MajVerStr, bufsize, TEXT(" 2008"));
        else if (osvi.dwMinorVersion == 1)
          StringCchCopy(MajVerStr, bufsize, TEXT(" 2008 R2"));
        else
          StringCchCopy(MajVerStr, bufsize, TEXT(" 6.x(unknown)"));
        StringCchCat(pszOS, bufsize, MajVerStr);
        StringCchCat(pszOS, bufsize, TEXT(" "));
      }
      // Vista 以降では GetProductInfo が使える
      PGPI pGPI = (PGPI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
      DWORD dwType;
      pGPI(6, 0, 0, 0, &dwType);
      switch (dwType) {
        // Windows Vista / 7
        case PRODUCT_ULTIMATE:
        case PRODUCT_ULTIMATE_N:
          StringCchCat(pszOS, bufsize, TEXT("Ultimate Edition"));
          break;
        case PRODUCT_HOME_BASIC:
        case PRODUCT_HOME_BASIC_N:
          StringCchCat(pszOS, bufsize, TEXT("Home Basic Edition"));
          break;
        case PRODUCT_HOME_PREMIUM:
        case PRODUCT_HOME_PREMIUM_N:
          StringCchCat(pszOS, bufsize, TEXT("Home Premium Edition"));
          break;
        case PRODUCT_ENTERPRISE:
        case PRODUCT_ENTERPRISE_N:
          StringCchCat(pszOS, bufsize, TEXT("Enterprise Edition"));
          break;
        case PRODUCT_BUSINESS:
        case PRODUCT_BUSINESS_N:
          StringCchCat(pszOS, bufsize, TEXT("Business Edition"));
          break;
        case PRODUCT_STARTER:
        case PRODUCT_STARTER_N:
          StringCchCat(pszOS, bufsize, TEXT("Starter Edition"));
          break;
        case PRODUCT_PROFESSIONAL:
        case PRODUCT_PROFESSIONAL_N:
          StringCchCat(pszOS, bufsize, TEXT("Professional Edition"));
          break;
        // Windows Server 2008 / R2
        case PRODUCT_STANDARD_SERVER:
        case PRODUCT_STANDARD_SERVER_CORE:
        case PRODUCT_STANDARD_SERVER_V:
        case PRODUCT_STANDARD_SERVER_CORE_V:
          StringCchCat(pszOS, bufsize, TEXT("Standard Edition"));
          break;
        case PRODUCT_DATACENTER_SERVER:
        case PRODUCT_DATACENTER_SERVER_CORE:
        case PRODUCT_DATACENTER_SERVER_V:
        case PRODUCT_DATACENTER_SERVER_CORE_V:
        StringCchCat(pszOS, bufsize, TEXT("Datacenter Edition"));
          break;
        case PRODUCT_ENTERPRISE_SERVER:
        case PRODUCT_ENTERPRISE_SERVER_CORE:
        case PRODUCT_ENTERPRISE_SERVER_V:
        case PRODUCT_ENTERPRISE_SERVER_CORE_V:
        case PRODUCT_ENTERPRISE_SERVER_IA64:
          StringCchCat(pszOS, bufsize, TEXT("Enterprise Edition"));
          if (dwType == PRODUCT_ENTERPRISE_SERVER_IA64)
            StringCchCat(pszOS, bufsize, TEXT(" for Itanium-based Systems"));
          break;
        case PRODUCT_WEB_SERVER:
        case PRODUCT_WEB_SERVER_CORE:
          StringCchCopy(pszOS, bufsize, TEXT("Windows Web Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          break;
        case PRODUCT_CLUSTER_SERVER: // Cluster Server Edition?
          StringCchCopy(pszOS, bufsize, TEXT("Windows HPC Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          break;
        case PRODUCT_HOME_SERVER:
        case PRODUCT_HOME_PREMIUM_SERVER: // Premium Edition?
          StringCchCopy(pszOS, bufsize, TEXT("Windows Home Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          if (dwType == PRODUCT_HOME_PREMIUM_SERVER)
            StringCchCat(pszOS, bufsize, TEXT(" Premium Edition"));
          break;
        case PRODUCT_SMALLBUSINESS_SERVER:
        case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
          StringCchCopy(pszOS, bufsize, TEXT("Windows Small Business Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          if (dwType == PRODUCT_SMALLBUSINESS_SERVER_PREMIUM)
            StringCchCat(pszOS, bufsize, TEXT(" Premium Edition"));
          break;
        case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
        case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
        case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
          StringCchCopy(pszOS, bufsize, TEXT("Windows Essential Business Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          StringCchCat(pszOS, bufsize, TEXT(" "));
          switch (dwType) {
            case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
              StringCchCat(pszOS, bufsize, TEXT("Management Server"));
            case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
              StringCchCat(pszOS, bufsize, TEXT("Security Server"));
            case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
              StringCchCat(pszOS, bufsize, TEXT("Messaging Server"));
          }
          break;
        case PRODUCT_SMALLBUSINESS_SERVER_PRIME:
          StringCchCat(pszOS, bufsize, TEXT("Foundation"));
          break;
        case PRODUCT_SERVER_FOR_SMALLBUSINESS:
          StringCchCat(pszOS, bufsize, TEXT("for Small Business Edition"));
          break;
        case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
          StringCchCat(pszOS, bufsize, TEXT("for Windows Essential Server Solutions"));
          break;
        case PRODUCT_HYPERV:
          StringCchCopy(pszOS, bufsize, TEXT("Hyper-V Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          break;
        case PRODUCT_STORAGE_EXPRESS_SERVER:
        case PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
        case PRODUCT_STORAGE_STANDARD_SERVER:
        case PRODUCT_STORAGE_STANDARD_SERVER_CORE:
        case PRODUCT_STORAGE_WORKGROUP_SERVER:
        case PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
        case PRODUCT_STORAGE_ENTERPRISE_SERVER:
        case PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
          StringCchCopy(pszOS, bufsize, TEXT("Windows Storage Server"));
          StringCchCat(pszOS, bufsize, MajVerStr);
          StringCchCat(pszOS, bufsize, TEXT(" "));
          switch (dwType) {
            case PRODUCT_STORAGE_EXPRESS_SERVER:
            case PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
              StringCchCopy(pszOS, bufsize, TEXT("Express"));
              break;
            case PRODUCT_STORAGE_STANDARD_SERVER:
            case PRODUCT_STORAGE_STANDARD_SERVER_CORE:
              StringCchCopy(pszOS, bufsize, TEXT("Standard"));
              break;
            case PRODUCT_STORAGE_WORKGROUP_SERVER:
            case PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
              StringCchCopy(pszOS, bufsize, TEXT("Workgroup"));
              break;
            case PRODUCT_STORAGE_ENTERPRISE_SERVER:
            case PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
              StringCchCopy(pszOS, bufsize, TEXT("Enterprise"));
              break;
          }
          StringCchCat(pszOS, bufsize, TEXT(" Edition"));
          break;
        default:
          StringCchCat(pszOS, bufsize, TEXT("Unknown Edition"));
      }
      // without Hyper-V
      switch (dwType) {
        case PRODUCT_STANDARD_SERVER_V:
        case PRODUCT_DATACENTER_SERVER_V:
        case PRODUCT_ENTERPRISE_SERVER_V:
        case PRODUCT_STANDARD_SERVER_CORE_V:
        case PRODUCT_DATACENTER_SERVER_CORE_V:
        case PRODUCT_ENTERPRISE_SERVER_CORE_V:
        case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
          StringCchCat(pszOS, bufsize, TEXT(" without Hyper-V"));
      }
      // core installation
      switch (dwType) {
        case PRODUCT_STANDARD_SERVER_CORE:
        case PRODUCT_DATACENTER_SERVER_CORE:
        case PRODUCT_ENTERPRISE_SERVER_CORE:
        case PRODUCT_WEB_SERVER_CORE:
        case PRODUCT_STANDARD_SERVER_CORE_V:
        case PRODUCT_DATACENTER_SERVER_CORE_V:
        case PRODUCT_ENTERPRISE_SERVER_CORE_V:
        case PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
        case PRODUCT_STORAGE_STANDARD_SERVER_CORE:
        case PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
        case PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
          StringCchCat(pszOS, bufsize, TEXT(" (core installation)"));
      }
      // x86 or x64
      if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
        StringCchCat(pszOS, bufsize, TEXT(", 64-bit"));
      else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
        StringCchCat(pszOS, bufsize, TEXT(", 32-bit"));
    }
 
    // Windows Server 2003 / XP x64 Edition
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
      if (osvi.wProductType == VER_NT_WORKSTATION) { // Windows XP Professional x64 Edition
        StringCchCopy(pszOS, bufsize, TEXT("Windows XP Professional"));
        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) // 必ず該当するはずだが
          StringCchCat(pszOS, bufsize, TEXT(" x64 Edition"));
      }
      else { // Windows Server 2003 ファミリー
        // Compute Cluster Server には R2 も x64 もつかない
        if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
          StringCchCopy(pszOS, bufsize, TEXT("Windows Compute Cluster Server 2003"));
        // Windows Home Server にも R2 はつかない (x64 は無い?)
        else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER)
          StringCchCopy(pszOS, bufsize, TEXT("Windows Home Server"));
        else {
          // Small Business か Storage か無印か
          if (osvi.wSuiteMask & (VER_SUITE_SMALLBUSINESS | VER_SUITE_SMALLBUSINESS_RESTRICTED))
            StringCchCopy(pszOS, bufsize, TEXT("Windows Small Business Server 2003"));
          else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
            StringCchCopy(pszOS, bufsize, TEXT("Windows Storage Server 2003"));
          else StringCchCopy(pszOS, bufsize, TEXT("Windows Server 2003"));
          // R2 か
          if (GetSystemMetrics(SM_SERVERR2))
            StringCchCat(pszOS, bufsize, TEXT(" R2"));
          // Edition
          StringCchCat(pszOS, bufsize, TEXT(", "));
          if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
            StringCchCat(pszOS, bufsize, TEXT("Datacenter"));
          else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
            StringCchCat(pszOS, bufsize, TEXT("Enterprise"));
          else if (osvi.wSuiteMask & VER_SUITE_BLADE)
            StringCchCat(pszOS, bufsize, TEXT("Web"));
          else StringCchCat(pszOS, bufsize, TEXT("Standard"));
          // x64 か
          if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
            StringCchCat(pszOS, bufsize, TEXT(" x64"));
          StringCchCat(pszOS, bufsize, TEXT(" Edition"));
          // IA64 か
          if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
            StringCchCat(pszOS, bufsize, TEXT(" for Itanium-based Systems"));
        }
      }
    }
 
    // XP
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
      StringCchCopy(pszOS, bufsize, TEXT("Windows XP "));
      if (GetSystemMetrics(SM_TABLETPC))
        StringCchCat(pszOS, bufsize, TEXT("Tablet PC Edition"));
      else if (GetSystemMetrics(SM_MEDIACENTER))
        StringCchCat(pszOS, bufsize, TEXT("Media Center Edition"));
      else if (GetSystemMetrics(SM_STARTER))
        StringCchCat(pszOS, bufsize, TEXT("Starter Edition"));
      else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
        StringCchCat(pszOS, bufsize, TEXT("Home Edition"));
      else if (osvi.wSuiteMask & (VER_SUITE_EMBEDDEDNT | VER_SUITE_EMBEDDED_RESTRICTED))
        StringCchCat(pszOS, bufsize, TEXT("Embedded"));
      else StringCchCat(pszOS, bufsize, TEXT("Professional"));
    }
 
    // 2000
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
      StringCchCopy(pszOS, bufsize, TEXT("Windows 2000 "));
      if (osvi.wProductType == VER_NT_WORKSTATION)
        StringCchCat(pszOS, bufsize, TEXT("Professional"));
      else {
        if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
          StringCchCat(pszOS, bufsize, TEXT("Datacenter "));
        else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
          StringCchCat(pszOS, bufsize, TEXT("Advanced "));
        StringCchCat(pszOS, bufsize, TEXT("Server"));
      }
    }
 
    // NT 3 / 4
    if (osvi.dwMajorVersion == 4 || osvi.dwMajorVersion == 3) {
      StringCchCopy(pszOS, bufsize, TEXT("Windows NT "));
      if (bOsVersionInfoEx) { // NT 4.0 SP6 だけのはず
        if (osvi.wProductType == VER_NT_WORKSTATION) {
          if (osvi.dwMajorVersion == 4)
            StringCchCat(pszOS, bufsize, TEXT("4.0"));
          else StringCchCat(pszOS, bufsize, TEXT("3.51")); // ないはずだが
          StringCchCat(pszOS, bufsize, TEXT(" Workstation"));
        }
        else {
          StringCchCat(pszOS, bufsize, TEXT("Server"));
          if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
            StringCchCat(pszOS, bufsize, TEXT(", Enterprise Edition"));
          else if (osvi.wSuiteMask & VER_SUITE_TERMINAL)
            StringCchCat(pszOS, bufsize, TEXT(", Terminal Server Edition"));
          else if (osvi.wSuiteMask & (VER_SUITE_EMBEDDEDNT | VER_SUITE_EMBEDDED_RESTRICTED))
            StringCchCat(pszOS, bufsize, TEXT(", Embedded Edition"));
          if (osvi.dwMajorVersion == 4)
            StringCchCat(pszOS, bufsize, TEXT(" 4.0"));
          else StringCchCat(pszOS, bufsize, TEXT(" 3.51")); // ないはずだが
        }
      }
      else { // NT 4.0 SP5 以前はレジストリから取得
        HKEY hKey;
        TCHAR szProductType[9] = TEXT("");
        DWORD dwBufLen = sizeof(TCHAR) * sizeof(szProductType);
        LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hKey);
        if (lRet == ERROR_SUCCESS) {
          lRet = RegQueryValueEx(hKey, TEXT("ProductType"), NULL, NULL, (LPBYTE)szProductType, &dwBufLen);
          RegCloseKey(hKey);
        }
        if (lstrcmpi(szProductType, TEXT("LANMANNT")) == 0)
          StringCchCat(pszOS, bufsize, TEXT(" Server"));
        if (lstrcmpi(szProductType, TEXT("SERVERNT")) == 0)
          StringCchCat(pszOS, bufsize, TEXT(" Server, Enterprise Edition"));
        if (osvi.dwMajorVersion == 4)
          StringCchCat(pszOS, bufsize, TEXT("4.0"));
        else StringCchCat(pszOS, bufsize, TEXT("3.51"));
        if (lstrcmpi(szProductType, TEXT("WINNT")) == 0)
          StringCchCat(pszOS, bufsize, TEXT(" Workstation"));
      }
    }
 
    // Service Pack
    if (_tcslen(osvi.szCSDVersion) > 0) {
      StringCchCat(pszOS, bufsize, TEXT(" ") );
      StringCchCat(pszOS, bufsize, osvi.szCSDVersion);
    }
 
    // build number
    TCHAR buf[80];
    StringCchPrintf(buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
    StringCchCat(pszOS, bufsize, buf);
    return TRUE; 
 
  }
 
  // 9x
  else if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
    switch (osvi.dwMinorVersion) {
      case 0:
        StringCchCopy(pszOS, bufsize, TEXT("Windows 95"));
        if (_tcschr(osvi.szCSDVersion, 'A'))
          StringCchCat(pszOS, bufsize, TEXT(" OSR1"));
        else if (_tcschr(osvi.szCSDVersion, 'B'))
          StringCchCat(pszOS, bufsize, TEXT(" OSR2"));
        else if (_tcschr(osvi.szCSDVersion, 'C'))
          StringCchCat(pszOS, bufsize, TEXT(" OSR2.5"));
        else StringCchCat(pszOS, bufsize, osvi.szCSDVersion); // ないはずだが
        break;
      case 10:
        StringCchCopy(pszOS, bufsize, TEXT("Windows 98"));
        if (_tcschr(osvi.szCSDVersion, 'A'))
          StringCchCat(pszOS, bufsize, TEXT(" Second Edition"));
        else StringCchCat(pszOS, bufsize, osvi.szCSDVersion); // ないはずだが
        break;
      case 90:
        StringCchCopy(pszOS, bufsize, TEXT("Windows Me"));
        break;
      default:
        StringCchCopy(pszOS, bufsize, TEXT("Windows 9x(unknown)")); // ないはずだが
    }
    return TRUE;
  }
 
  // NT でも 9x でもない (Win32s?)
  else {
    StringCchCopy(pszOS, bufsize, TEXT("Unknown Windows"));
    return FALSE;
  }
}
 
void _tmain(int argc, _TCHAR* argv[])
{
  TCHAR pszOS[256];
  if (GetOSDisplayString(pszOS, sizeof(pszOS)))
    MessageBox(NULL, pszOS, TEXT("Get OS Display String"), MB_OK);
  else
    MessageBox(NULL, TEXT("OS のバージョンを取得できませんでした"), TEXT("Get OS Display String"), MB_OK | MB_ICONERROR);
}

以上だ。

Visual C++ 2005 Standard、Visual C++ 2008 Express Editon でビルドできることを確認した。

BCC には対応していないが、もし BCC で使いたければ、下記の定数定義

#define VER_SUITE_PERSONAL              0x00000200
#define VER_SUITE_BLADE                 0x00000400
#define VER_SUITE_EMBEDDED_RESTRICTED   0x00000800
#define VER_SUITE_SECURITY_APPLIANCE    0x00001000
#define VER_SUITE_STORAGE_SERVER        0x00002000
#define VER_SUITE_COMPUTE_SERVER        0x00004000
#define PROCESSOR_ARCHITECTURE_AMD64    9

を追加し、#include <strsafe.h> を削除し、StringCchCopy を _tcscpy に、StringCchCat を _tcscat に、StringCchPrintf を _stprintf にそれぞれ置き換えればおそらくコンパイルできるだろう。

本日のツッコミ(全7件) [ツッコミを入れる]
_ (2009/06/28 08:28)

めんどくさすぎてワロタww

_ p (2009/06/29 01:54)

バージョン判別だけなら GetVersionEx 使うだけなんですが、エディション判別が絡むと途端に複雑化しますぇ…

_ (2009/06/30 23:33)

MSアホすぐるwww

_ T.M.神無月 (2010/03/08 16:36)

このプログラムを自分のライブラリ(のちに公開予定)にそのまま使わせてもらってもよろしいでしょうか?

_ p (2010/03/09 00:48)

はい、どうぞご自由にどうぞ。
ちなみに Vista 以降だったら HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName 読むだけでいいんじゃね? という話もあったりなかったり…

_ ipa (2011/04/05 14:47)

228,230行にbreakがないですよ

_ らま (2011/05/24 10:51)

GetProductInfoの第2引数はosvi.dwMinorVersionですね。
でないと、Windows 7 Professional Edition が Windows 7 Business Edition になってしまいます。
ここの"Remarks"を参照下さい。→http://msdn.microsoft.com/en-us/library/ms724358%28v=VS.85%29.aspx
実機でも確認しました。