From: Jan Dubois Date: Tue, 29 Jul 2003 19:14:10 +0000 (-0700) Subject: Extend Win32::GetOSVersion() to return additional information X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3e5269857e8d8838cbf4c53cbb042865abeedd0e;p=p5sagit%2Fp5-mst-13.2.git Extend Win32::GetOSVersion() to return additional information Message-ID: p4raw-id: //depot/perl@20331 --- diff --git a/lib/Win32.pod b/lib/Win32.pod index b2a4ac6..d0a6263 100644 --- a/lib/Win32.pod +++ b/lib/Win32.pod @@ -205,12 +205,12 @@ available drive letter. =item Win32::GetOSVersion() -[CORE] Returns the array (STRING, MAJOR, MINOR, BUILD, ID), where the +[CORE] Returns the list (STRING, MAJOR, MINOR, BUILD, ID), where the elements are, respectively: An arbitrary descriptive string, the major version number of the operating system, the minor version number, the build number, and a digit indicating the actual operating system. -For the ID, the values are 0 for Win32s, 1 for Windows 9X and 2 for -Windows NT/2000/XP. In scalar context it returns just the ID. +For the ID, the values are 0 for Win32s, 1 for Windows 9X/Me and 2 for +Windows NT/2000/XP/2003. In scalar context it returns just the ID. Currently known values for ID MAJOR and MINOR are as follows: @@ -223,10 +223,41 @@ Currently known values for ID MAJOR and MINOR are as follows: Windows NT 4 2 4 0 Windows 2000 2 5 0 Windows XP 2 5 1 - Windows .NET Server 2 5 1 - -Unfortunately as of June 2002 there is no way to distinguish between -.NET servers and XP servers without using additional modules. + Windows Server 2003 2 5 2 + +On Windows NT 4 SP6 and later this function returns the following +additional values: SPMAJOR, SPMINOR, SUITEMASK, PRODUCTTYPE. + +SPMAJOR and SPMINOR are are the version numbers of the latest +installed service pack. + +SUITEMASK is a bitfield identifying the product suites available on +the system. Known bits are: + + VER_SUITE_SMALLBUSINESS 0x00000001 + VER_SUITE_ENTERPRISE 0x00000002 + VER_SUITE_BACKOFFICE 0x00000004 + VER_SUITE_COMMUNICATIONS 0x00000008 + VER_SUITE_TERMINAL 0x00000010 + VER_SUITE_SMALLBUSINESS_RESTRICTED 0x00000020 + VER_SUITE_EMBEDDEDNT 0x00000040 + VER_SUITE_DATACENTER 0x00000080 + VER_SUITE_SINGLEUSERTS 0x00000100 + VER_SUITE_PERSONAL 0x00000200 + VER_SUITE_BLADE 0x00000400 + VER_SUITE_EMBEDDED_RESTRICTED 0x00000800 + VER_SUITE_SECURITY_APPLIANCE 0x00001000 + +The VER_SUITE_xxx names are listed here to crossreference the Microsoft +documentation. The Win32 module does not provide symbolic names for these +constants. + +PRODUCTTYPE provides additional information about the system. It should +be one of the following integer values: + + 1 - Workstation (NT 4, 2000 Pro, XP Home, XP Pro) + 2 - Domaincontroller + 3 - Server =item Win32::GetOSName() @@ -239,7 +270,7 @@ GetOSVersion() in list context. Currently the possible values for the OS name are - Win32s Win95 Win98 WinMe Win2000 WinXP/.Net WinNT3.51 WinNT4 + Win32s Win95 Win98 WinMe WinNT3.51 WinNT4 Win2000 WinXP/.Net Win2003 This routine is just a simple interface into GetOSVersion(). More specific or demanding situations should use that instead. Another @@ -247,6 +278,11 @@ option would be to use POSIX::uname(), however the latter appears to report only the OS family name and not the specific OS. In scalar context it returns just the ID. +The name "WinXP/.Net" is used for historical reasons only, to maintain +backwards compatibility of the Win32 module. Windows .NET Server has +been renamed as Windows 2003 Server before final release and uses a +different major/minor version number than Windows XP. + =item Win32::GetShortPathName(PATHNAME) [CORE] Returns a representation of PATHNAME composed only of diff --git a/win32/win32.c b/win32/win32.c index c41c36d..beabef6 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4502,26 +4502,68 @@ static XS(w32_GetOSVersion) { dXSARGS; - OSVERSIONINFOA osver; + /* Use explicit struct definition because wSuiteMask and + * wProductType are not defined in the VC++ 6.0 headers. + * WORD type has been replaced by unsigned short because + * WORD is already used by Perl itself. + */ + struct { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[128]; + unsigned short wServicePackMajor; + unsigned short wServicePackMinor; + unsigned short wSuiteMask; + BYTE wProductType; + BYTE wReserved; + } osver; + BOOL bEx = TRUE; if (USING_WIDE()) { - OSVERSIONINFOW osverw; + struct { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + WCHAR szCSDVersion[128]; + unsigned short wServicePackMajor; + unsigned short wServicePackMinor; + unsigned short wSuiteMask; + BYTE wProductType; + BYTE wReserved; + } osverw; char szCSDVersion[sizeof(osverw.szCSDVersion)]; - osverw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); - if (!GetVersionExW(&osverw)) { - XSRETURN_EMPTY; + osverw.dwOSVersionInfoSize = sizeof(osverw); + if (!GetVersionExW((OSVERSIONINFOW*)&osverw)) { + bEx = FALSE; + osverw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (!GetVersionExW((OSVERSIONINFOW*)&osverw)) { + XSRETURN_EMPTY; + } } W2AHELPER(osverw.szCSDVersion, szCSDVersion, sizeof(szCSDVersion)); XPUSHs(newSVpvn(szCSDVersion, strlen(szCSDVersion))); - osver.dwMajorVersion = osverw.dwMajorVersion; - osver.dwMinorVersion = osverw.dwMinorVersion; - osver.dwBuildNumber = osverw.dwBuildNumber; - osver.dwPlatformId = osverw.dwPlatformId; + osver.dwMajorVersion = osverw.dwMajorVersion; + osver.dwMinorVersion = osverw.dwMinorVersion; + osver.dwBuildNumber = osverw.dwBuildNumber; + osver.dwPlatformId = osverw.dwPlatformId; + osver.wServicePackMajor = osverw.wServicePackMajor; + osver.wServicePackMinor = osverw.wServicePackMinor; + osver.wSuiteMask = osverw.wSuiteMask; + osver.wProductType = osverw.wProductType; } else { - osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA(&osver)) { - XSRETURN_EMPTY; + osver.dwOSVersionInfoSize = sizeof(osver); + if (!GetVersionExA((OSVERSIONINFOA*)&osver)) { + bEx = FALSE; + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA*)&osver)) { + XSRETURN_EMPTY; + } } XPUSHs(newSVpvn(osver.szCSDVersion, strlen(osver.szCSDVersion))); } @@ -4529,6 +4571,12 @@ XS(w32_GetOSVersion) XPUSHs(newSViv(osver.dwMinorVersion)); XPUSHs(newSViv(osver.dwBuildNumber)); XPUSHs(newSViv(osver.dwPlatformId)); + if (bEx) { + XPUSHs(newSViv(osver.wServicePackMajor)); + XPUSHs(newSViv(osver.wServicePackMinor)); + XPUSHs(newSViv(osver.wSuiteMask)); + XPUSHs(newSViv(osver.wProductType)); + } PUTBACK; }