Author Topic: OSVERSION not working as expected  (Read 2767 times)

Jeff

  • Administrator
  • Newbie
  • *****
  • Posts: 40
    • View Profile
OSVERSION not working as expected
« on: December 07, 2019, 01:58:24 PM »
A couple of issues with the new OSVERSION code and what I did to attempt a fix on my copy of 7.3.6.

First, OS_Win_10 is missing from EmitOSVersionEnum function (starting around line 14369), so I can't get anything using OSVERSION to even compile
(error #2048: Undeclared identifier 'OS_Win_10' (did you mean 'OS_Win_8'?)

This was easy to fix by adding OS_Win_10 to EmitOSVersionEnum. 
Code: [Select]
SUB EmitOSVersionEnum()
  FPRINT FP_ENU, ""
  FPRINT FP_ENU, "enum"
  FPRINT FP_ENU, "  {"
  FPRINT FP_ENU, "  OSUnknown = -2,"
  FPRINT FP_ENU, "  OSError = -1,"
  FPRINT FP_ENU, "  OS_3x,"
  FPRINT FP_ENU, "  OS_95,"
  FPRINT FP_ENU, "  OS_98,"
  FPRINT FP_ENU, "  OS_ME,"
  FPRINT FP_ENU, "  OS_NT3,"
  FPRINT FP_ENU, "  OS_2000,"
  FPRINT FP_ENU, "  OS_XP,"
  FPRINT FP_ENU, "  OS_XP_Pro_x64,"
  FPRINT FP_ENU, "  OS_Server_2003,"
  FPRINT FP_ENU, "  OS_Home_Server,"
  FPRINT FP_ENU, "  OS_Server_2003_R2,"
  FPRINT FP_ENU, "  OS_Vista,"
  FPRINT FP_ENU, "  OS_Server_2008,"
  FPRINT FP_ENU, "  OS_Server_2008_R2,"
  FPRINT FP_ENU, "  OS_Win_7,"
  FPRINT FP_ENU, "  OS_Server_2012,"
  FPRINT FP_ENU, "  OS_Win_8,"
  FPRINT FP_ENU, "  OS_Win_10"
  FPRINT FP_ENU, "  };"
  FPRINT FP_ENU, ""
END SUB

A simple program using OSVERSION will now compile, but is returning 17 (Win10) on my Win7 machine.  So that means the new consolidated Win10OrNewer function is returning TRUE on my Win7 machine. 

I don't know why, but the "if (dwMaj >= 10)" comparison (around line 20763) is returning TRUE whether it actually is or not.  I changed it to "if ((int)dwMaj >= 10)" and now it's returning proper results on my mix of Win7 and Win10 machines.  So, no issues at all with 32-bit, but got this warning when trying to compile the same simple OSVERSION test program to 64-bit
(warning #2235: Not all control paths return a value)

I added else return false to clear that up, so the Win10OrNewer output now looks like this:
Code: [Select]
    FPRINT FP_WRITE,"BOOL Win10OrNewer(void)"
    FPRINT FP_WRITE,"{"
    FPRINT FP_WRITE," OSVERSIONINFO osvi = { 0 };"
    FPRINT FP_WRITE," OSVERSIONINFOEX osviex = { 0 };"
    FPRINT FP_WRITE," DWORD dwMaj = { 0 };"
    FPRINT FP_WRITE," NTSTATUS(WINAPI * RtlGetVersion) (LPOSVERSIONINFOEX);"
    FPRINT FP_WRITE," osvi.dwOSVersionInfoSize = sizeof(osvi);"
    FPRINT FP_WRITE," GetVersionEx(&osvi);"
    FPRINT FP_WRITE," if (osvi.dwMajorVersion >= 6)"
    FPRINT FP_WRITE," {"
    FPRINT FP_WRITE," *(FARPROC *) & RtlGetVersion = GetProcAddress(GetModuleHandle(", ENC$("ntdll"), "), ", ENC$("RtlGetVersion"), ");"
    FPRINT FP_WRITE," if (RtlGetVersion)"
    FPRINT FP_WRITE," {"
    FPRINT FP_WRITE," osviex.dwOSVersionInfoSize = sizeof(osviex);"
    FPRINT FP_WRITE," RtlGetVersion(&osviex);"
    FPRINT FP_WRITE," }"
    FPRINT FP_WRITE," dwMaj = osviex.dwMajorVersion;"
    FPRINT FP_WRITE," }"
    FPRINT FP_WRITE," else"
    FPRINT FP_WRITE," {"
    FPRINT FP_WRITE," dwMaj = osvi.dwMajorVersion;"
    FPRINT FP_WRITE," }"
    FPRINT FP_WRITE," if ((int)dwMaj >= 10)"
    FPRINT FP_WRITE," {"
    FPRINT FP_WRITE," return TRUE;"
    FPRINT FP_WRITE," }"
    FPRINT FP_WRITE," else"
    FPRINT FP_WRITE," {"
    FPRINT FP_WRITE," return FALSE;"
    FPRINT FP_WRITE," }"

These changes appear to be working properly for me, but I've honestly never messed around with bc.bas, so I'd like more eyes on this.

Thanks,
Jeff


MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 1885
    • View Profile
Re: OSVERSION not working as expected
« Reply #1 on: December 07, 2019, 04:45:21 PM »
Hi Jeff ... After applying your updates, Mingw and Pelles compile PRINT OSVERSION correctly as 32 and 64 bit images and all return 17.

Now, on the downside,  LccWin32 is incapable of handling the new OSVERSION.  Not your fault and not surprising when you consider
many of LccWin32's headers are 10 to 20 years old and LccWin32/64 hasn't been updated in over three years.  I expect anyone who is
still using LccWin32 exclusively (... crickets... )  has some hard lessons coming their way.  On that point, I am nearly finished converting
all of the classic BCX demos to build using Pelles tools exclusively.  LccWin32 had a good run but it's clear that Jacob has put a fork in it.


Error:  undeclared identifier 'SM_SERVERR2'
Error:  undeclared identifier 'VER_SUITE_WH_SERVER'
Error:  undeclared identifier 'PROCESSOR_ARCHITECTURE_AMD64'
Error:  undeclared identifier 'RtlGetVersion'
Error:  illegal use of type name 'LPOSVERSIONINFOEX'

Warning: possible usage of PROCESSOR_ARCHITECTURE_AMD64 before definition
Warning: possible usage of VER_SUITE_WH_SERVER before definition
Warning: possible usage of SM_SERVERR2 before definition
Warning: missing prototype for NTSTATUS

Robert

  • Hero Member
  • *****
  • Posts: 1142
    • View Profile
Re: OSVERSION not working as expected
« Reply #2 on: December 08, 2019, 04:29:52 PM »
Below is my consolidation of the OSVERSION code with Win10OrNewer. I have added detection for Windows 8.1, Server 2012 R2 and Server 2016 and eliminated the use of GetVersionEx for determining the Major Version. This has not been extensively tested but it does work with Pelle's C and my Windows 10 machine. There are three code blocks to replace. Try it, you might like it.

First ENUM block, to locate, search for for "return values for OSVersion"

Code: [Select]
ENUM
  OSUnknown = -2
  OSError = -1
  OS_3x
  OS_95
  OS_98
  OS_ME
  OS_NT3
  OS_2000
  OS_XP
  OS_XP_Pro_x64
  OS_Server_2003
  OS_Home_Server
  OS_Server_2003_R2
  OS_Vista
  OS_Server_2008
  OS_Server_2008_R2
  OS_Win_7
  OS_Server_2012
  OS_Win_8
  OS_Win_81
  OS_Server_2012_R2
  OS_Win_10
  OS_Server_2016
END ENUM

Second ENUM block, to locate, search for for "SUB EmitOSVersionEnum()"

Code: [Select]
SUB EmitOSVersionEnum()
    FPRINT FP_ENU, ""
    FPRINT FP_ENU, "enum"
    FPRINT FP_ENU, "  {"
    FPRINT FP_ENU, "  OSUnknown = -2,"
    FPRINT FP_ENU, "  OSError = -1,"
    FPRINT FP_ENU, "  OS_3x,"
    FPRINT FP_ENU, "  OS_95,"
    FPRINT FP_ENU, "  OS_98,"
    FPRINT FP_ENU, "  OS_ME,"
    FPRINT FP_ENU, "  OS_NT3,"
    FPRINT FP_ENU, "  OS_2000,"
    FPRINT FP_ENU, "  OS_XP,"
    FPRINT FP_ENU, "  OS_XP_Pro_x64,"
    FPRINT FP_ENU, "  OS_Server_2003,"
    FPRINT FP_ENU, "  OS_Home_Server,"
    FPRINT FP_ENU, "  OS_Server_2003_R2,"
    FPRINT FP_ENU, "  OS_Vista,"
    FPRINT FP_ENU, "  OS_Server_2008,"
    FPRINT FP_ENU, "  OS_Server_2008_R2,"
    FPRINT FP_ENU, "  OS_Win_7,"
    FPRINT FP_ENU, "  OS_Server_2012,"
    FPRINT FP_ENU, "  OS_Win_8,"
    FPRINT FP_ENU, "  OS_Win_81,"
    FPRINT FP_ENU, "  OS_Server_2012_R2,"
    FPRINT FP_ENU, "  OS_Win_10,"
    FPRINT FP_ENU, "  OS_Server_2016"
    FPRINT FP_ENU, "  };"
    FPRINT FP_ENU, ""
END SUB

OSVersion function, to locate, search for "Use_OSVersion"

Code: [Select]
  IF Use_OSVersion THEN
    IF Use_Library THEN FPRINT FP_WRITE, "// BCXRTLIB: OSVersion"
    FPRINT FP_WRITE, "int OSVersion (void) {"
    FPRINT FP_WRITE, "  OSVERSIONINFOEXW  osvi={0};"
    FPRINT FP_WRITE, "  osvi.dwOSVersionInfoSize=sizeof(osvi);"
    FPRINT FP_WRITE, "  NTSTATUS (WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);"
    FPRINT FP_WRITE, "  *(FARPROC*)&RtlGetVersion=GetProcAddress(GetModuleHandle(" &DQ$ & "ntdll" & DQ$ & "), " & DQ$ & "RtlGetVersion" & DQ$ & ");"
    FPRINT FP_WRITE, "    if (RtlGetVersion == NULL)"
    FPRINT FP_WRITE, "       {"
    FPRINT FP_WRITE, "       GetVersionEx((LPOSVERSIONINFO)&osvi);"
    FPRINT FP_WRITE, "       }"
    FPRINT FP_WRITE, "    else "
    FPRINT FP_WRITE, "       {"
    FPRINT FP_WRITE, "       RtlGetVersion(&osvi);"
    FPRINT FP_WRITE, "       }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "  switch (osvi.dwPlatformId)"
    FPRINT FP_WRITE, "    {"
    FPRINT FP_WRITE, "    case VER_PLATFORM_WIN32_NT:"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==10 && osvi.dwMinorVersion==0)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        if(osvi.wProductType == VER_NT_WORKSTATION)           return  OS_Win_10;"
    FPRINT FP_WRITE, "        return  OS_Server_2016;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==6 && osvi.dwMinorVersion==3)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        if(osvi.wProductType == VER_NT_WORKSTATION)           return  OS_Win_81;"
    FPRINT FP_WRITE, "        return  OS_Server_2012_R2;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==6 && osvi.dwMinorVersion==2)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        if(osvi.wProductType == VER_NT_WORKSTATION)           return  OS_Win_8;"
    FPRINT FP_WRITE, "        return  OS_Server_2012;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==6 && osvi.dwMinorVersion==1)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        if(osvi.wProductType == VER_NT_WORKSTATION)            return OS_Win_7;"
    FPRINT FP_WRITE, "        return OS_Server_2008_R2;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==6 && osvi.dwMinorVersion==0)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        if(osvi.wProductType != VER_NT_WORKSTATION)             return OS_Server_2008;"
    FPRINT FP_WRITE, "        return OS_Vista;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion>=5 && osvi.dwMinorVersion>=2)"
    FPRINT FP_WRITE, "        {"
    FPRINT FP_WRITE, "        int iTestForSM_SERVERR2;"
    FPRINT FP_WRITE, "        iTestForSM_SERVERR2 = GetSystemMetrics(SM_SERVERR2);"
    FPRINT FP_WRITE, "        if(iTestForSM_SERVERR2 != 0)                            return OS_Server_2003_R2;"
    FPRINT FP_WRITE, "        if((osvi.wSuiteMask & VER_SUITE_WH_SERVER) != 0)        return OS_Home_Server;"
    FPRINT FP_WRITE, "        if (iTestForSM_SERVERR2 == 0)                           return OS_Server_2003;"
    FPRINT FP_WRITE, "        SYSTEM_INFO siSysInfo;"
    FPRINT FP_WRITE, "        GetSystemInfo(&siSysInfo); "
    FPRINT FP_WRITE, "        if((osvi.wProductType == VER_NT_WORKSTATION) && (siSysInfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)) return OS_XP_Pro_x64;"
    FPRINT FP_WRITE, "        return OSUnknown;"
    FPRINT FP_WRITE, "        }"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1)      return OS_XP;"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0)      return OS_2000;"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "      if(osvi.dwMajorVersion==3 && osvi.dwMinorVersion==51)     return OS_NT3;"
    FPRINT FP_WRITE, "      return OSUnknown;"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "    case VER_PLATFORM_WIN32_WINDOWS:"
    FPRINT FP_WRITE, "      if((osvi.dwMajorVersion==4 && osvi.dwMinorVersion==90))   return OS_ME;"
    FPRINT FP_WRITE, "      if((osvi.dwMajorVersion==4 && osvi.dwMinorVersion==10))   return OS_98;"
    FPRINT FP_WRITE, "      if((osvi.dwMajorVersion==4 && osvi.dwMinorVersion==0))    return OS_95;"
    FPRINT FP_WRITE, "      return OSUnknown;"
    FPRINT FP_WRITE, ""
    FPRINT FP_WRITE, "    case VER_PLATFORM_WIN32s:"
    FPRINT FP_WRITE, "      return OS_3x;"
    FPRINT FP_WRITE, "    }"
    FPRINT FP_WRITE, "  return OSUnknown;"
    FPRINT FP_WRITE, sENDBCXRTLIB$
  END IF



MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 1885
    • View Profile
Re: OSVERSION not working as expected
« Reply #3 on: December 08, 2019, 06:04:49 PM »
PRINT
PRINT "MrBcx has a Windows 10 PC ..."
PRINT
PRINT "The BCX enumerated value for OS_WIN_10 is:", OS_Win_10
PRINT
PRINT "The value returned from the new OSVERSION function is:", osversion
PRINT
PRINT "MrBcx says, 'So far, so good!  Thank you Robert Wishlaw!'"


**************************************************************************

C:\Temp\737>test

MrBcx has a Windows 10 PC ...

The BCX enumerated value for OS_WIN_10 is: 19

The value returned from the new OSVERSION function is: 19

MrBcx says, 'So far, so good!  Thank you Robert Wishlaw!'


MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 1885
    • View Profile
Re: OSVERSION not working as expected
« Reply #4 on: December 11, 2019, 08:55:52 AM »
Not hearing anymore feedback on this subject, I'm going to tempt fate and upload 7.3.7
containing Robert Wishlaw's OSVERSION updates before his efforts get lost in the ether.

I will also update the BCX ONLINE HELP to reflect the folllowing values that are returned from this updated function:


OS_3x             =  0
OS_95             =  1
OS_98             =  2
OS_ME             =  3
OS_NT3            =  4
OS_2000           =  5
OS_XP             =  6
OS_XP_Pro_x64     =  7
OS_Server_2003    =  8
OS_Home_Server    =  9
OS_Server_2003_R2 =  10
OS_Vista          =  11
OS_Server_2008    =  12
OS_Server_2008_R2 =  13
OS_Win_7          =  14
OS_Server_2012    =  15
OS_Win_8          =  16
OS_Win_81         =  17
OS_Server_2012_R2 =  18
OS_Win_10         =  19
OS_Server_2016    =  20
« Last Edit: December 11, 2019, 10:43:18 AM by MrBcx »

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 1885
    • View Profile
Re: OSVERSION not working as expected
« Reply #5 on: January 21, 2020, 01:43:54 PM »
First off, I'm not suggesting that there is anything wrong with the current OSVERSION function.

Now ... I stumbled upon a 2017 post by Pierre Bellisle on the PowerBasic forum today and
subsequently used the information to create a different kind of OSVERSION function.
I named it WindowsVersion(), to keep things simple to understand.

Here is that function and a one-liner demonstration: 

Code: [Select]

PRINT WindowsVersion!()


FUNCTION WindowsVersion AS SINGLE
  LOCAL OsInfoEx AS OSVERSIONINFOEXW
'-----------------------------------
'                RETURN VALUES
'-----------------------------------
' Ten         =      10.0
' Eight.One   =       6.3
' Eight.Zero  =       6.2
' Seven       =       6.1
' Vista       =       6.0
' 2003        =       5.2
' XP          =       5.1
' 2000        =       5.0
'-----------------------------------
  RtlGetVersion(LIB "NtDll.dll", &OsInfoEx)
  FUNCTION = OsInfoEx.dwMajorVersion+(OsInfoEx.dwMinorVersion/IIF(OsInfoEx.dwMinorVersion>9,100,10))
END FUNCTION



I tested this on my Windows 10 Pro machine and on a Windows 7 Pro running on Virtual box.
Both tests yielded the correct return values  ( 10 and 6.1 respectively )

My hunch is that most people don't have a need to test for anything older than Windows 2000, or more
granular than the versions that this function yields.  The icing on the cake is that the return values match
some common values used by Microsoft to identify versions of Windows versus the 0 through 20 that our
built-in OSVERSION produces.

https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version

This is just another tool for your toolbox -- use it if you need it.

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 1885
    • View Profile
Re: OSVERSION not working as expected
« Reply #6 on: January 26, 2020, 12:17:26 PM »
Seems I can't leave this thread alone  8)

I have restored Lcc-Win32 compatibility to the BCX OSVERSION function and will be included in 7.4.1. 

The changes will not affect any other compiler.

-MrBcx-