VistaのEditionを調べる方法

VistaのEditionを調べたくなったのですが、GetProductInfoというVistaから追加されたWinAPIで取得できるようです。が、XPなどでも動作させたい場合はGetProcAddressを使うのが吉。てなわけで以下のような感じになります。

void CTestVistaEditionDlg::OnBnClickedButton1()
{
enum {
OS_PRODUCT_BUSINESS = 0x00000006,                        // Business Edition
OS_PRODUCT_BUSINESS_N = 0x00000010,                        // Business Edition
OS_PRODUCT_CLUSTER_SERVER = 0x00000012,                    // Cluster Server Edition
OS_PRODUCT_DATACENTER_SERVER = 0x00000008,                // Server Datacenter Edition (full installation)
OS_PRODUCT_DATACENTER_SERVER_CORE = 0x0000000C,            // Server Datacenter Edition (core installation)
OS_PRODUCT_ENTERPRISE = 0x00000004,                        // Enterprise Edition
OS_PRODUCT_ENTERPRISE_N = 0x0000001B,                    // Enterprise Edition
OS_PRODUCT_ENTERPRISE_SERVER = 0x0000000A,                // Server Enterprise Edition (full installation)
OS_PRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E,        // Server Enterprise Edition (core installation)
OS_PRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F,            // Server Enterprise Edition for Itanium-based Systems
OS_PRODUCT_HOME_BASIC = 0x00000002,                        // Home Basic Edition
OS_PRODUCT_HOME_BASIC_N = 0x00000005,                    // Home Basic Edition
OS_PRODUCT_HOME_PREMIUM = 0x00000003,                    // Home Premium Edition
OS_PRODUCT_HOME_PREMIUM_N = 0x0000001A,                    // Home Premium Edition
OS_PRODUCT_HOME_SERVER = 0x00000013,                    // Home Server Edition
OS_PRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018,        // Server for Small Business Edition
OS_PRODUCT_SMALLBUSINESS_SERVER = 0x00000009,            // Small Business Server
OS_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019,    // Small Business Server Premium Edition
OS_PRODUCT_STANDARD_SERVER = 0x00000007,                // Server Standard Edition (full installation)
OS_PRODUCT_STANDARD_SERVER_CORE  = 0x0000000D,            // Server Standard Edition (core installation)
OS_PRODUCT_STARTER = 0x0000000B,                        // Starter Edition
OS_PRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017,        // Storage Server Enterprise Edition
OS_PRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014,            // Storage Server Express Edition
OS_PRODUCT_STORAGE_STANDARD_SERVER = 0x00000015,        // Storage Server Standard Edition
OS_PRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016,        // Storage Server Workgroup Edition
OS_PRODUCT_UNDEFINED = 0x00000000,                        // An unknown product
OS_PRODUCT_ULTIMATE = 0x00000001,                        // Ultimate Edition
OS_PRODUCT_ULTIMATE_N = 0x0000001C,                        // Ultimate Edition
OS_PRODUCT_WEB_SERVER = 0x00000011,                        // Web Server Edition
};
DWORD dwOsProduct = OS_PRODUCT_UNDEFINED;
CString strEdition;
CString strDescription;
typedef BOOL (WINAPI *GETPRODUCTINFO)(DWORD, DWORD, DWORD, DWORD, PDWORD);
GETPRODUCTINFO pfGetProductInfo = NULL;
HMODULE hModule = GetModuleHandle(_T("kernel32.dll"));
if (hModule) {
pfGetProductInfo = (GETPRODUCTINFO)::GetProcAddress(hModule, "GetProductInfo");
}
if (pfGetProductInfo)
{
BOOL bRet = FALSE;
OSVERSIONINFOEX osvi;
::ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bRet = ::GetVersionEx((OSVERSIONINFO*)&osvi);
DWORD dwReturnedProductType = OS_PRODUCT_UNDEFINED;
if (pfGetProductInfo(osvi.dwMajorVersion,osvi.dwMinorVersion,
osvi.wServicePackMajor,osvi.wServicePackMinor,&dwReturnedProductType))
{
dwOsProduct = dwReturnedProductType;
}
}
//
switch (dwOsProduct)
{
case OS_PRODUCT_BUSINESS:
strDescription = _T("Business Edition");
break;
case OS_PRODUCT_BUSINESS_N:
strDescription = _T("Business Edition");
break;
case OS_PRODUCT_CLUSTER_SERVER:
strDescription = _T("Cluster Server Edition");
break;
case OS_PRODUCT_DATACENTER_SERVER:
strDescription = _T("Server Datacenter Edition (full installation)");
break;
case OS_PRODUCT_DATACENTER_SERVER_CORE:
strDescription = _T("Server Datacenter Edition (core installation)");
break;
case OS_PRODUCT_ENTERPRISE:
strDescription = _T("Enterprise Edition");
break;
case OS_PRODUCT_ENTERPRISE_N:
strDescription = _T("Enterprise Edition");
break;
case OS_PRODUCT_ENTERPRISE_SERVER:
strDescription = _T("Server Enterprise Edition (full installation)");
break;
case OS_PRODUCT_ENTERPRISE_SERVER_CORE:
strDescription = _T("Server Enterprise Edition (core installation)");
break;
case OS_PRODUCT_ENTERPRISE_SERVER_IA64:
strDescription = _T("Server Enterprise Edition for Itanium-based Systems");
break;
case OS_PRODUCT_HOME_BASIC:
strDescription = _T("Home Basic Edition");
break;
case OS_PRODUCT_HOME_BASIC_N:
strDescription = _T("Home Basic Edition");
break;
case OS_PRODUCT_HOME_PREMIUM:
strDescription = _T("Home Premium Edition");
break;
case OS_PRODUCT_HOME_PREMIUM_N:
strDescription = _T("Home Premium Edition");
break;
case OS_PRODUCT_HOME_SERVER:
strDescription = _T("Home Server Edition");
break;
case OS_PRODUCT_SERVER_FOR_SMALLBUSINESS:
strDescription = _T("Server for Small Business Edition");
break;
case OS_PRODUCT_SMALLBUSINESS_SERVER:
strDescription = _T("Small Business Server");
break;
case OS_PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
strDescription = _T("Small Business Server Premium Edition");
break;
case OS_PRODUCT_STANDARD_SERVER:
strDescription = _T("Server Standard Edition (full installation)");
break;
case OS_PRODUCT_STANDARD_SERVER_CORE :
strDescription = _T("Server Standard Edition (core installation)");
break;
case OS_PRODUCT_STARTER:
strDescription = _T("Starter Edition");
break;
case OS_PRODUCT_STORAGE_ENTERPRISE_SERVER:
strDescription = _T("Storage Server Enterprise Edition");
break;
case OS_PRODUCT_STORAGE_EXPRESS_SERVER:
strDescription = _T("Storage Server Express Edition");
break;
case OS_PRODUCT_STORAGE_STANDARD_SERVER:
strDescription = _T("Storage Server Standard Edition");
break;
case OS_PRODUCT_STORAGE_WORKGROUP_SERVER:
strDescription = _T("Storage Server Workgroup Edition");
break;
case OS_PRODUCT_UNDEFINED:
strDescription = _T("An unknown product");
break;
case OS_PRODUCT_ULTIMATE:
strDescription = _T("Ultimate Edition");
break;
case OS_PRODUCT_ULTIMATE_N:
strDescription = _T("Ultimate Edition");
break;
case OS_PRODUCT_WEB_SERVER:
strDescription = _T("Web Server Edition");
break;
}
strEdition.Format(_T("dwOsProduct = %08x (%s)"),dwOsProduct,strDescription);
this->m_strVistaProduct = strEdition;
this->UpdateData(FALSE);
}

ただし、OSVERSIONINFOEXは98系は対応していないので98/Meで動作させたい場合はさらに工夫が必要です。(OSVERSIONINFOEXに対してGetProcAddressのNullチェックをすればよいでしょう)