From db4f96f255e423ee355bfc9f614b8ebbc3582ed2 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 8 Dec 2008 07:33:41 +0000 Subject: [PATCH] improve windows version detection --- ext/standard/info.c | 276 +++++++++++++++++++++++++++++++++++------- ext/standard/winver.h | 82 +++++++++++++ 2 files changed, 317 insertions(+), 41 deletions(-) create mode 100755 ext/standard/winver.h diff --git a/ext/standard/info.c b/ext/standard/info.c index 0e4b5da941..68a9bffb2d 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -339,6 +339,220 @@ PHPAPI char *php_info_html_esc(char *string TSRMLS_DC) } /* }}} */ +#ifdef PHP_WIN32 +/* {{{ */ +typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); +typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); + +#include "winver.h" + +#if _MSC_VER < 1300 +#define OSVERSIONINFOEX php_win_OSVERSIONINFOEX +#endif + +char* php_get_windows_name() +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + PGNSI pGNSI; + PGPI pGPI; + BOOL bOsVersionInfoEx; + DWORD dwType; + char *major = NULL, *sub = NULL, *retval; + + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (!(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))) { + return NULL; + } + + pGNSI = (PGNSI) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetNativeSystemInfo"); + if(NULL != pGNSI) { + pGNSI(&si); + } else { + GetSystemInfo(&si); + } + + if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion > 4 ) { + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 ) { + if (osvi.wProductType == VER_NT_WORKSTATION) { + major = "Windows Vista"; + } else { + major = "Windows Server 2008"; + } + + pGPI = (PGPI) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProductInfo"); + pGPI(6, 0, 0, 0, &dwType); + + switch (dwType) { + case PRODUCT_ULTIMATE: + sub = "Ultimate Edition"; + break; + case PRODUCT_HOME_PREMIUM: + sub = "Home Premium Edition"; + break; + case PRODUCT_HOME_BASIC: + sub = "Home Basic Edition"; + break; + case PRODUCT_ENTERPRISE: + sub = "Enterprise Edition"; + break; + case PRODUCT_BUSINESS: + sub = "Business Edition"; + break; + case PRODUCT_STARTER: + sub = "Starter Edition"; + break; + case PRODUCT_CLUSTER_SERVER: + sub = "Cluster Server Edition"; + break; + case PRODUCT_DATACENTER_SERVER: + sub = "Datacenter Edition"; + break; + case PRODUCT_DATACENTER_SERVER_CORE: + sub = "Datacenter Edition (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER: + sub = "Enterprise Edition"; + break; + case PRODUCT_ENTERPRISE_SERVER_CORE: + sub = "Enterprise Edition (core installation)"; + break; + case PRODUCT_ENTERPRISE_SERVER_IA64: + sub = "Enterprise Edition for Itanium-based Systems"; + break; + case PRODUCT_SMALLBUSINESS_SERVER: + sub = "Small Business Server"; + break; + case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + sub = "Small Business Server Premium Edition"; + break; + case PRODUCT_STANDARD_SERVER: + sub = "Standard Edition"; + break; + case PRODUCT_STANDARD_SERVER_CORE: + sub = "Standard Edition (core installation)"; + break; + case PRODUCT_WEB_SERVER: + sub = "Web Server Edition"; + break; + } + } + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 ) { + if (GetSystemMetrics(SM_SERVERR2)) + major = "Windows Server 2003 R2"; + else if (osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER) + major = "Windows Storage Server 2003"; + else if (osvi.wSuiteMask==VER_SUITE_WH_SERVER) + major = "Windows Home Server"; + else if (osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { + major = "Windows XP Professional x64 Edition"; + } else { + major = "Windows Server 2003"; + } + + /* Test for the server type. */ + if ( osvi.wProductType != VER_NT_WORKSTATION ) { + if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 ) { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + sub = "Datacenter Edition for Itanium-based Systems"; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + sub = "Enterprise Edition for Itanium-based Systems"; + } + + else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + sub = "Datacenter x64 Edition"; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + sub = "Enterprise x64 Edition"; + else sub = "Standard x64 Edition"; + } else { + if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER ) + sub = "Compute Cluster Edition"; + else if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + sub = "Datacenter Edition"; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + sub = "Enterprise Edition"; + else if ( osvi.wSuiteMask & VER_SUITE_BLADE ) + sub = "Web Edition"; + else sub = "Standard Edition"; + } + } + } + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) { + major = "Windows XP"; + if( osvi.wSuiteMask & VER_SUITE_PERSONAL ) + sub = "Home Edition"; + else sub = "Professional"; + } + + if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 ) { + major = "Windows 2000"; + + if (osvi.wProductType == VER_NT_WORKSTATION ) { + sub = "Professional"; + } else { + if( osvi.wSuiteMask & VER_SUITE_DATACENTER ) + sub = "Datacenter Server"; + else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE ) + sub = "Advanced Server"; + else sub = "Server"; + } + } + } else { + return NULL; + } + + spprintf(&retval, 0, "%s%s%s%s%s", major, sub?" ":"", sub?sub:"", osvi.szCSDVersion[0] != '\0'?" ":"", osvi.szCSDVersion); + return retval; +} +/* }}} */ + +/* {{{ */ +void php_get_windows_cpu(char *buf, int bufsize) +{ + SYSTEM_INFO SysInfo; + GetSystemInfo(&SysInfo); + switch (SysInfo.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL : + snprintf(buf, bufsize, "i%d", SysInfo.dwProcessorType); + break; + case PROCESSOR_ARCHITECTURE_MIPS : + snprintf(buf, bufsize, "MIPS R%d000", SysInfo.wProcessorLevel); + break; + case PROCESSOR_ARCHITECTURE_ALPHA : + snprintf(buf, bufsize, "Alpha %d", SysInfo.wProcessorLevel); + break; + case PROCESSOR_ARCHITECTURE_PPC : + snprintf(buf, bufsize, "PPC 6%02d", SysInfo.wProcessorLevel); + break; + case PROCESSOR_ARCHITECTURE_IA64 : + snprintf(buf, bufsize, "IA64"); + break; +#if defined(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) + case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 : + snprintf(buf, bufsize, "IA32"); + break; +#endif +#if defined(PROCESSOR_ARCHITECTURE_AMD64) + case PROCESSOR_ARCHITECTURE_AMD64 : + snprintf(buf, bufsize, "AMD64"); + break; +#endif + case PROCESSOR_ARCHITECTURE_UNKNOWN : + default: + snprintf(buf, bufsize, "Unknown"); + break; + } +} +/* }}} */ +#endif + /* {{{ php_get_uname */ PHPAPI char *php_get_uname(char mode) @@ -352,10 +566,8 @@ PHPAPI char *php_get_uname(char mode) DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; - SYSTEM_INFO SysInfo; - + GetComputerName(ComputerName, &dwSize); - GetSystemInfo(&SysInfo); if (mode == 's') { if (dwVersion < 0x80000000) { @@ -369,52 +581,34 @@ PHPAPI char *php_get_uname(char mode) } else if (mode == 'n') { php_uname = ComputerName; } else if (mode == 'v') { + char *winver = php_get_windows_name(); dwBuild = (DWORD)(HIWORD(dwVersion)); - snprintf(tmp_uname, sizeof(tmp_uname), "build %d", dwBuild); + if(winver == NULL) { + snprintf(tmp_uname, sizeof(tmp_uname), "build %d", dwBuild); + } else { + snprintf(tmp_uname, sizeof(tmp_uname), "build %d (%s)", dwBuild, winver); + } php_uname = tmp_uname; - } else if (mode == 'm') { - switch (SysInfo.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_INTEL : - snprintf(tmp_uname, sizeof(tmp_uname), "i%d", SysInfo.dwProcessorType); - php_uname = tmp_uname; - break; - case PROCESSOR_ARCHITECTURE_MIPS : - snprintf(tmp_uname, sizeof(tmp_uname), "MIPS R%d000", SysInfo.wProcessorLevel); - php_uname = tmp_uname; - break; - case PROCESSOR_ARCHITECTURE_ALPHA : - snprintf(tmp_uname, sizeof(tmp_uname), "Alpha %d", SysInfo.wProcessorLevel); - php_uname = tmp_uname; - break; - case PROCESSOR_ARCHITECTURE_PPC : - snprintf(tmp_uname, sizeof(tmp_uname), "PPC 6%02d", SysInfo.wProcessorLevel); - php_uname = tmp_uname; - break; - case PROCESSOR_ARCHITECTURE_IA64 : - php_uname = "IA64"; - break; -#if defined(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) - case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 : - php_uname = "IA32"; - break; -#endif -#if defined(PROCESSOR_ARCHITECTURE_AMD64) - case PROCESSOR_ARCHITECTURE_AMD64 : - php_uname = "AMD64"; - break; -#endif - case PROCESSOR_ARCHITECTURE_UNKNOWN : - default : - php_uname = "Unknown"; - break; + if(winver) { + efree(winver); } + } else if (mode == 'm') { + php_get_windows_cpu(tmp_uname, sizeof(tmp_uname)); + php_uname = tmp_uname; } else { /* assume mode == 'a' */ /* Get build numbers for Windows NT or Win95 */ if (dwVersion < 0x80000000){ + char *winver = php_get_windows_name(); + char wincpu[20]; + + php_get_windows_cpu(wincpu, sizeof(wincpu)); dwBuild = (DWORD)(HIWORD(dwVersion)); - snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d build %d", + snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d build %d (%s) %s", "Windows NT", ComputerName, - dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild); + dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild, winver?winver:"unknown", wincpu); + if(winver) { + efree(winver); + } } else { snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d", "Windows 9x", ComputerName, diff --git a/ext/standard/winver.h b/ext/standard/winver.h new file mode 100755 index 0000000000..ae5026e717 --- /dev/null +++ b/ext/standard/winver.h @@ -0,0 +1,82 @@ +#ifndef _PHP_WINVER_H +#define _PHP_WINVER_H + +#ifndef SM_SERVERR2 +#define SM_SERVERR2 89 +#endif +#ifndef VER_SUITE_WH_SERVER +#define VER_SUITE_WH_SERVER 0x8000 +#endif + +#ifndef PRODUCT_ULTIMATE +#define PRODUCT_UNDEFINED 0x00000000 +#define PRODUCT_ULTIMATE 0x00000001 +#define PRODUCT_HOME_BASIC 0x00000002 +#define PRODUCT_HOME_PREMIUM 0x00000003 +#define PRODUCT_ENTERPRISE 0x00000004 +#define PRODUCT_HOME_BASIC_N 0x00000005 +#define PRODUCT_BUSINESS 0x00000006 +#define PRODUCT_STANDARD_SERVER 0x00000007 +#define PRODUCT_DATACENTER_SERVER 0x00000008 +#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 +#define PRODUCT_ENTERPRISE_SERVER 0x0000000A +#define PRODUCT_STARTER 0x0000000B +#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C +#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D +#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E +#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F +#define PRODUCT_BUSINESS_N 0x00000010 +#define PRODUCT_WEB_SERVER 0x00000011 +#define PRODUCT_CLUSTER_SERVER 0x00000012 +#define PRODUCT_HOME_SERVER 0x00000013 +#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 +#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 +#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 +#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 +#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 +#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 +#endif + +#ifndef VER_NT_WORKSTATION +#define VER_NT_WORKSTATION 0x0000001 +#define VER_NT_DOMAIN_CONTROLLER 0x0000002 +#define VER_NT_SERVER 0x0000003 +#endif + +#ifndef VER_SUITE_SMALLBUSINESS +#define VER_SUITE_SMALLBUSINESS 0x00000001 +#define VER_SUITE_ENTERPRISE 0x00000002 +#define VER_SUITE_BACKOFFICE 0x00000004 +#define VER_SUITE_COMMUNICATIONS 0x00000008 +#define VER_SUITE_TERMINAL 0x00000010 +#define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020 +#define VER_SUITE_EMBEDDEDNT 0x00000040 +#define VER_SUITE_DATACENTER 0x00000080 +#define VER_SUITE_SINGLEUSERTS 0x00000100 +#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 +#endif + +#ifndef PROCESSOR_ARCHITECTURE_AMD64 +#define PROCESSOR_ARCHITECTURE_AMD64 9 +#endif + +typedef struct _php_win_OSVERSIONINFOEXA { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[128]; + WORD wServicePackMajor; + WORD wServicePackMinor; + WORD wSuiteMask; + BYTE wProductType; + BYTE wReserved; +} php_win_OSVERSIONINFOEX; + +#endif \ No newline at end of file -- 2.50.1