]> granicus.if.org Git - php/commitdiff
improve Windows version detection
authorStanislav Malyshev <stas@php.net>
Mon, 8 Dec 2008 07:32:14 +0000 (07:32 +0000)
committerStanislav Malyshev <stas@php.net>
Mon, 8 Dec 2008 07:32:14 +0000 (07:32 +0000)
ext/standard/info.c
ext/standard/winver.h [new file with mode: 0755]

index 2f21bd79fc3be5ee44a942415eb07d0e9ecb3644..dd64c312ca2615e615312734a8eb2fc8d6f8f647 100644 (file)
@@ -238,6 +238,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)
@@ -251,10 +465,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) {
@@ -268,52 +480,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 (executable)
index 0000000..ae5026e
--- /dev/null
@@ -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