Windows 8 and 8.1
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Windows 8 and 8.1
http://www.codeproject.com/Articles/678 ... n-of-GetVe
Perhaps Fred can change the code behind OSVersion() to the code given in the above article.
Perhaps Fred can change the code behind OSVersion() to the code given in the above article.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Windows 8 and 8.1
I laughed at the CodeProject link where they said this:
"It can take anywhere from 5-15 Milliseconds on a Physical System.
It took upward of 30 Milliseconds on a Virtual Machine to Execute.
Since This API can be can called many times during an Application's
life cycle [...]"
I mean, come on! You don't call this sort of thing over and over.
The OS isn't going to change during an app's runtime. Just call it
once, store the value, and you're done.
"It can take anywhere from 5-15 Milliseconds on a Physical System.
It took upward of 30 Milliseconds on a Virtual Machine to Execute.
Since This API can be can called many times during an Application's
life cycle [...]"
I mean, come on! You don't call this sort of thing over and over.
The OS isn't going to change during an app's runtime. Just call it
once, store the value, and you're done.

I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
"PureBasic won't be object oriented, period" - Fred.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Windows 8 and 8.1
I really do think MS have lost the plot, it really does not have to be so complicated. They probably should have continued with GetVersionEx(), but for apps that only need to report the version, a simple string record would be fine. Any apps compiled for a lesser version could be automatically run in compatibility mode couldn't they? Then the 'Version Lie' would be redundant.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Windows 8 and 8.1
I tried to see if it's possible to avoid to add a manifest to force GetVersionEx to not lie.
Can you test this different approach and tell me if it does work ?
From my tests it does.
PB 5.20
Can you test this different approach and tell me if it does work ?
From my tests it does.
PB 5.20
Code: Select all
Procedure.i GetOSVersion (*Major.Integer, *Minor.Integer, *Build.Integer)
; [DESC]
; Get the version number of the OS on which the program is running.
;
; [OUTPUT]
; *Major : The major version number (for example: 6).
; *Minor : The minor version number (for example: 1).
; *Build : The build number (for example: 7601).
;
; [RETURN]
; 1 if successful, else 0.
; see http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074%28v=vs.85%29.aspx
; see http://msdn.microsoft.com/en-us/library/windows/hardware/ff561910%28v=vs.85%29.aspx
; 6.1.7600 Win 7
; 6.1.7601 Win 7 SP1
; 6.2.9200 Win 8.0
; 6.3.9600 Win 8.1
Protected osvex.OSVERSIONINFOEX
Protected *fp, hDLL, major, minor, build
Protected fail
osvex\dwOSVersionInfoSize = SizeOf(osvex)
fail = 1
If GetVersionEx_(@osvex)
fail = 0
major = osvex\dwMajorVersion
minor = osvex\dwMinorVersion
build = osvex\dwBuildNumber
If (major = 6 And minor = 2) ; windows 8 ... we double check this
fail = 1
hDLL = OpenLibrary (#PB_Any, "ntdll.dll")
If hDLL
*fp = GetFunction(hDLL, "RtlGetVersion")
If *fp And CallFunctionFast(*fp, @osvex) = 0 ; #STATUS_SUCCESS
fail = 0
major = osvex\dwMajorVersion
minor = osvex\dwMinorVersion
build = osvex\dwBuildNumber
EndIf
CloseLibrary(hDLL)
EndIf
EndIf
EndIf
If fail
*Major\i = 0
*Minor\i = 0
*Build\i = 0
ProcedureReturn 0
Else
*Major\i = major
*Minor\i = minor
*Build\i = build
ProcedureReturn 1
EndIf
EndProcedure
Define maj, min, bld
Debug GetOSVersion(@maj, @min, @bld)
Debug "maj = " + maj
Debug "min = " + min
Debug "bld = " + bld
"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review
Re: Windows 8 and 8.1
Results from W8.1 PB5.21B2
1
maj = 6
min = 3
bld = 9600
It seems to work.
Jim
1
maj = 6
min = 3
bld = 9600
It seems to work.
Jim
Re: Windows 8 and 8.1
Nice snippet luis
With WMI we can get all what we need in one shot
In case WMI is stopped Run "net start winmgmt"
Tested with Win 8.1 x64
With WMI we can get all what we need in one shot
In case WMI is stopped Run "net start winmgmt"
Tested with Win 8.1 x64
Code: Select all
; class Win32_OperatingSystem : CIM_OperatingSystem
; {
; string BootDevice;
; string BuildNumber;
; string BuildType;
; string Caption;
; string CodeSet;
; string CountryCode;
; string CreationClassName;
; string CSCreationClassName;
; string CSDVersion;
; string CSName;
; sint16 CurrentTimeZone;
; boolean DataExecutionPrevention_Available;
; boolean DataExecutionPrevention_32BitApplications;
; boolean DataExecutionPrevention_Drivers;
; uint8 DataExecutionPrevention_SupportPolicy;
; boolean Debug;
; string Description;
; boolean Distributed;
; uint32 EncryptionLevel;
; uint8 ForegroundApplicationBoost;
; uint64 FreePhysicalMemory;
; uint64 FreeSpaceInPagingFiles;
; uint64 FreeVirtualMemory;
; datetime InstallDate;
; uint32 LargeSystemCache;
; datetime LastBootUpTime;
; datetime LocalDateTime;
; string Locale;
; string Manufacturer;
; uint32 MaxNumberOfProcesses;
; uint64 MaxProcessMemorySize;
; string MUILanguages[];
; string Name;
; uint32 NumberOfLicensedUsers;
; uint32 NumberOfProcesses;
; uint32 NumberOfUsers;
; uint32 OperatingSystemSKU;
; string Organization;
; string OSArchitecture;
; uint32 OSLanguage;
; uint32 OSProductSuite;
; uint16 OSType;
; string OtherTypeDescription;
; Boolean PAEEnabled;
; string PlusProductID;
; string PlusVersionNumber;
; boolean PortableOperatingSystem;
; boolean Primary;
; uint32 ProductType;
; string RegisteredUser;
; string SerialNumber;
; uint16 ServicePackMajorVersion;
; uint16 ServicePackMinorVersion;
; uint64 SizeStoredInPagingFiles;
; string Status;
; uint32 SuiteMask;
; string SystemDevice;
; string SystemDirectory;
; string SystemDrive;
; uint64 TotalSwapSpaceSize;
; uint64 TotalVirtualMemorySize;
; uint64 TotalVisibleMemorySize;
; string Version;
; string WindowsDirectory;
; };
#COINIT_MULTITHREAD=0
#RPC_C_AUTHN_LEVEL_CONNECT=2
#RPC_C_IMP_LEVEL_IDENTIFY=2
#EOAC_NONE=0
#RPC_C_AUTHN_WINNT=10
#RPC_C_AUTHZ_NONE=0
#RPC_C_AUTHN_LEVEL_CALL=3
#RPC_C_IMP_LEVEL_IMPERSONATE=3
#CLSCTX_INPROC_SERVER=1
#wbemFlagReturnImmediately=16
#wbemFlagForwardOnly=32
#IFlags = #wbemFlagReturnImmediately + #wbemFlagForwardOnly
#WBEM_INFINITE=$FFFFFFFF
#WMISeparator=","
Procedure.l ansi2uni(ansi.s)
size.l=MultiByteToWideChar_(#CP_ACP,0,ansi,-1,0,0)
Dim unicode.w(size)
MultiByteToWideChar_(#CP_ACP, 0, ansi, Len(ansi), unicode(), size)
ProcedureReturn SysAllocString_(@unicode())
EndProcedure
Procedure uni2ansi(uni)
Shared WMIResult.s
WMIResult.s = ""
mem=uni
While PeekW (mem)
WMIResult=WMIResult+Chr(PeekW(mem))
mem=mem+2
Wend
ProcedureReturn @WMIResult
EndProcedure
ProcedureDLL.s WMI(WMICommand.s)
CoInitializeEx_(0,#COINIT_MULTITHREAD)
hres=CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT, #RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0)
If hres <> 0: MessageRequester("ERROR", "unable to call CoInitializeSecurity", #MB_OK): Goto cleanup: EndIf
hres=CoCreateInstance_(?CLSID_WbemLocator,0, #CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc.IWbemLocator)
If hres <> 0: MessageRequester("ERROR", "unable to call CoCreateInstance", #MB_OK): Goto cleanup: EndIf
CompilerIf #PB_Compiler_Unicode
hres=loc\ConnectServer(SysAllocString_(@"root\cimv2"),0,0,0,0,0,0,@svc.IWbemServices)
CompilerElse
hres=loc\ConnectServer(ansi2uni("root\cimv2"),0,0,0,0,0,0,@svc.IWbemServices)
CompilerEndIf
If hres <> 0: MessageRequester("ERROR", "unable to call IWbemLocator::ConnectServer", #MB_OK): Goto cleanup: EndIf
hres=svc\QueryInterface(?IID_IUnknown,@pUnk.IUnknown)
hres=CoSetProxyBlanket_(svc,#RPC_C_AUTHN_WINNT, #RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL, #RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf
hres=CoSetProxyBlanket_(pUnk,#RPC_C_AUTHN_WINNT, #RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL, #RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf
pUnk\Release()
k=CountString(WMICommand,#WMISeparator)
Dim wmitxt$(k)
For i=0 To k
wmitxt$(i) = StringField(WMICommand,i+1,#WMISeparator)
Next
CompilerIf #PB_Compiler_Unicode
hres=svc\ExecQuery(SysAllocString_(@"WQL"), SysAllocString_(@wmitxt$(0)), #IFlags,0,@pEnumerator.IEnumWbemClassObject)
CompilerElse
hres=svc\ExecQuery(ansi2uni("WQL"),ansi2uni(wmitxt$(0)), #IFlags,0,@pEnumerator.IEnumWbemClassObject)
CompilerEndIf
If hres <> 0: MessageRequester("ERROR", "unable to call IWbemServices::ExecQuery", #MB_OK): Goto cleanup: EndIf
hres=pEnumerator\reset()
Repeat
hres=pEnumerator\Next(#WBEM_INFINITE, 1, @pclsObj.IWbemClassObject, @uReturn)
For i=1 To k
mem=AllocateMemory(1000)
CompilerIf #PB_Compiler_Unicode
hres=pclsObj\get(SysAllocString_(@wmitxt$(i)), 0, mem, 0, 0)
CompilerElse
hres=pclsObj\get(ansi2uni(wmitxt$(i)), 0, mem, 0, 0)
CompilerEndIf
Type=PeekW(mem)
Select Type
Case 8
val.s=PeekS(uni2ansi(PeekL(mem+8)))
Case 3
val.s=Str(PeekL(mem+8))
Default
val.s=""
EndSelect
If uReturn <> 0: wmi$=wmi$+wmitxt$(i)+" = "+val+Chr(10)+Chr(13): EndIf
FreeMemory(mem)
Next
Until uReturn = 0
cleanup:
svc\Release()
loc\Release()
pEnumerator\Release()
pclsObj\Release()
CoUninitialize_()
ProcedureReturn wmi$
EndProcedure
Text$ = WMI("Select * FROM Win32_OperatingSystem,Name")
Debug StringField(Text$,1, "|")
Debug WMI("Select * FROM Win32_OperatingSystem,Version")
Debug WMI("Select * FROM Win32_OperatingSystem,OSArchitecture")
DataSection
CLSID_IEnumWbemClassObject:
Data.l $1B1CAD8C
Data.w $2DAB, $11D2
Data.b $B6, $04, $00, $10, $4B, $70, $3E, $FD
IID_IEnumWbemClassObject:
Data.l $7C857801
Data.w $7381, $11CF
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
CLSID_WbemLocator:
Data.l $4590F811
Data.w $1D3A, $11D0
Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24
IID_IWbemLocator:
Data.l $DC12A687
Data.w $737F, $11CF
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
IID_IUnknown:
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection
Egypt my love
Re: Windows 8 and 8.1
@TassyJim -> Thanks
@RASHAD -> Thanks, I try to avoid WMI if possible though... don't know really why, but another option is always welcomed
If you ask someone "Are you using Windows 7 ?" and he's running Win 7 SP1 he would likely reply: "Yes".
If you ask someone "Are you using Windows 8 ?" and he's running Win 8.1 he would likely reply: "No 8.1".
@RASHAD -> Thanks, I try to avoid WMI if possible though... don't know really why, but another option is always welcomed

I think that's because the compatibility mode for an EXE is stored in the registry, so every time you copy a new file over an older one the path it's still the same and so the new EXE just inherits the settings.Thade wrote: I hopped with an USB-Stick and new copies of a program between my LapTop (Win 8.1) and another PC (Win 7) for half an hour until I noticed that the Program, which tested the OS Version was set to Win XP compatibility before. And every new version I copied over the old one had still this mode set.
Code: Select all
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
I think too it should differentiate between 8.0 and 8.1.PureGuy wrote: However, I think PB's OSVersion() functions should be updated.
If you ask someone "Are you using Windows 7 ?" and he's running Win 7 SP1 he would likely reply: "Yes".
If you ask someone "Are you using Windows 8 ?" and he's running Win 8.1 he would likely reply: "No 8.1".
"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review
Re: Windows 8 and 8.1
Well, I would say: "yes, Windows 8.1"...luis wrote:If you ask someone "Are you using Windows 8 ?" and he's running Win 8.1 he would likely reply: "No 8.1".

If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
Re: Windows 8 and 8.1
Windows 8.1. and the up coming Windows 10 will only admit their real version if you program's manifest claims to be compatible. Otherwise, for example, Windows 8.1 will claim to be Windows 8. To get around this your 'program' has to claim to be compatible via its manifest. To solve this for Pure Basic a compatibility manifest needs to be added in the resources. This is the manifest outline Microsoft uses.
This is from > http://msdn.microsoft.com/en-us/library ... 85%29.aspx
where its noted on that page:
That's why the old tried and true methods people have used in Pure Basic return windows 8 for what is really windows 8.1.
Code: Select all
<exe>.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name=SXS_ASSEMBLY_NAME
version=SXS_ASSEMBLY_VERSION
processorArchitecture=SXS_PROCESSOR_ARCHITECTURE
/>
<description> my app exe </description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"
/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
* <!-- Windows 8.1 -->
* <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
</assembly>
where its noted on that page:
Which also means that if you are trying to get the version info for Windows 8.1 and it returns as windows 8 even though its really windows 8.1 that your 'app' or the method being used to get the windows version does not include the 'required' manifest information to specifically target windows 8.1.In Windows 8.1, the GetVersion(Ex) APIs have been deprecated. That means that while you can still call the APIs, if your app does not specifically target Windows 8.1, you will get Windows 8 versioning (6.2.0.0).
That's why the old tried and true methods people have used in Pure Basic return windows 8 for what is really windows 8.1.
The world and human nature was screwed up before I was born. It's not my fault and I'm just stuck with trying to deal with the mess left behind, so don't blame me.
Re: Windows 8 and 8.1
@smacker
Wasn't all this and more already stated in the thread, link included
Wasn't all this and more already stated in the thread, link included

"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review
Re: Windows 8 and 8.1
This is my first version from that link mentioned by IdeasVacuum further back in this thread (http://www.codeproject.com/Articles/678 ... n-of-GetVe) - wanted to check out the viability of using it.
can someone test this for Windows 8 and and 8.1, and if you have the preview build of Windows 10 on that also?
note that it only calls the ansi version of the VerifyVersionInfo function from the API, make the necessary corrections if you want unicode and call the unicode version, yes, I could have done the CompilerIf thing but I didn't here.
Microsoft , and others examples i've seen, uses a macro called VER_SET_CONDITION instead of calling the VerSetConditionMask function directly each time. The macro just calls VerSetConditionMask function some way or another anyway from what i've read. So here is the macro instead if you want to use it:
to use the macro insert it above the procedure, you still need to call it for each test condition so for the above code replace these lines:
with these:
It seems to work compiled 64 bit Windows 7, but does not work when compiled 32 bit in Windows 7 and VerifyVersionInfo comes back with error code 1150 (using GetLastError) which translates to "The specified program requires a newer version of Windows." so i'm not sure if thats because it does not work in 32 bit at all or there is something else odd going on. I haven't read anything yet which indicates its 64 bit only.
Here is another version for testing, its a version of the ' IsWindows7OrGreater' version helper functions from the API which can't be called directly from the dll in Pure Basic > http://msdn.microsoft.com/en-us/library ... 85%29.aspx
So, if someone could check it out and see how it works out for windows 8 and 8.1 .... don't have access to a windows 8 machine right now, waiting for a new hard drive to arrive for it.
thanks
can someone test this for Windows 8 and and 8.1, and if you have the preview build of Windows 10 on that also?
note that it only calls the ansi version of the VerifyVersionInfo function from the API, make the necessary corrections if you want unicode and call the unicode version, yes, I could have done the CompilerIf thing but I didn't here.
Code: Select all
Prototype PVerifyVersionInfo(lpVersionInfo.l, dwTypeMask.l, dwlConditionMask.q) : Global VerifyVersionInfo.PVerifyVersionInfo
Prototype PRtlZeroMemory(mem, sze) : Global ZeroMemory.PRtlZeroMemory
Prototype PVerSetConditionMask(in_ULONGLONG_dwlConditionMask.q, in_DWORD_dwTypeBitMask.l, in_BYTE_dwConditionMask.b)
Global VerSetConditionMask.PVerSetConditionMask
Lib_Kernel32 = OpenLibrary(#PB_Any, "Kernel32.dll")
If IsLibrary(Lib_Kernel32)
isLib_Kernel32.b = #True
VerifyVersionInfo.PVerifyVersionInfo=GetFunction(Lib_Kernel32,"VerifyVersionInfoA")
VerSetConditionMask.PVerSetConditionMask=GetFunction(Lib_Kernel32,"VerSetConditionMask")
ZeroMemory.PRtlZeroMemory=GetFunction(Lib_Kernel32,"RtlZeroMemory")
Else
isLib_Kernel32.b = #False
EndIf
#VER_MINORVERSION = $0000001
#VER_MAJORVERSION = $0000002
#VER_SERVICEPACKMINOR = $0000010
#VER_SERVICEPACKMAJOR = $0000020
#VER_BUILDNUMBER = $0000004
#VER_MAJORVERSION = $0000002
#VER_MINORVERSION = $0000001
#VER_PLATFORMID = $0000008
#VER_PRODUCT_TYPE = $0000080
#VER_SERVICEPACKMAJOR = $0000020
#VER_SERVICEPACKMINOR = $0000010
#VER_SUITENAME = $0000040
#VER_EQUAL = 1 ; The current value must be equal to the specified value..
#VER_GREATER = 2 ; The current value must be greater than the specified value.
#VER_GREATER_EQUAL = 3 ; The current value must be greater than or equal to the specified value.
#VER_LESS = 4 ; The current value must be less than the specified value.
#VER_LESS_EQUAL = 5 ; The current value must be less than or equal to the specified value.
; for VerSetConditionMask function if dwTypeBitMask is #VER_SUITENAME the dwConditionMask parameter can be one of the following values.
#VER_AND = 6 ; All product suites specified in the wSuiteMask member must be present in the current system.
#VER_OR = 7 ; At least one of the specified product suites must be present in the current system.
Procedure TestOSVersion(major.l, minor.l, prodtype.b)
osvi.OSVERSIONINFOEX
dwlConditionMask.q = 0
; dwMajorVersion for windows 7, 8, 8.1, and 10 are all 6 so we really only need to check for the minor version
; but we use a procedure input here so its not hard coded so can be changed in case we want to test for other versions
osvi\dwOSVersionInfoSize = SizeOf(OSVERSIONINFOEX)
osvi\dwMajorVersion = major
osvi\dwMinorVersion = minor
;wversion\dwMinorVersion = 0 for Windows Vista, and Windows Server 2008
;wversion\dwMinorVersion = 1 for Windows 7, and Windows Server 2008 R2
;wversion\dwMinorVersion = 2 for Windows 8, and Windows Server 2012
;wversion\dwMinorVersion = 3 for Windows 8.1, and Windows Server 2012 R2
;wversion\dwMinorVersion = 4 for Windows 10
osvi\wProductType = prodtype ; #VER_NT_SERVER ; or #VER_NT_WORKSTATION depending on if we test for workstation or server
; for example:
; major/minor on windows server 2008 R2 is same as windows 7 workstation so we need to diffrentiate via prodtype variable input
; major/minor on Windows Server 2012 is same as Windows 8 workstation so we need to diffrentiate via prodtype variable input
; major/minor on Windows Server 2012 R2 is same as windows 8.1 workstation so we need to diffrentiate via prodtype variable input
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MAJORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MINORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_PRODUCT_TYPE, #VER_EQUAL)
isorisnotos = VerifyVersionInfo(osvi, #VER_MAJORVERSION|#VER_MINORVERSION|#VER_PRODUCT_TYPE, dwlConditionMask)
; If the operating system this is run in satisfies the specified requirements in the procedure input parameters the return value is a nonzero value.
; If the operating system this is run in does not satisfy the specified requirements in the procedure input parameters the return value is zero
ProcedureReturn isorisnotos
EndProcedure
Debug TestOSVersion(6, 0, #VER_NT_WORKSTATION) ;Windows Vista
Debug TestOSVersion(6, 0, #VER_NT_SERVER) ;Windows Vista
Debug TestOSVersion(6, 1, #VER_NT_WORKSTATION) ;Windows 7
Debug TestOSVersion(6, 1, #VER_NT_SERVER) ;Windows 7
Debug TestOSVersion(6, 2, #VER_NT_WORKSTATION) ;Windows 8
Debug TestOSVersion(6, 2, #VER_NT_SERVER) ;Windows 8
Debug TestOSVersion(6, 3, #VER_NT_WORKSTATION) ;Windows 8.1
Debug TestOSVersion(6, 3, #VER_NT_SERVER) ;Windows 8.1
Debug TestOSVersion(6, 4, #VER_NT_WORKSTATION) ;Windows 10
Debug TestOSVersion(6, 4, #VER_NT_SERVER) ;Windows 10
Code: Select all
Macro VER_SET_CONDITION(ConditionMask, VER, op)
VerSetConditionMask(ConditionMask, VER, op)
EndMacro
Code: Select all
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MAJORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MINORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_PRODUCT_TYPE, #VER_EQUAL)
with these:
Code: Select all
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_MAJORVERSION, #VER_EQUAL)
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_MINORVERSION, #VER_EQUAL)
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_PRODUCT_TYPE, #VER_EQUAL)
Here is another version for testing, its a version of the ' IsWindows7OrGreater' version helper functions from the API which can't be called directly from the dll in Pure Basic > http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Code: Select all
Procedure IsWindows7OrGreater(prodtype.b)
osvi.OSVERSIONINFOEX
dwlConditionMask.q = 0
; dwMajorVersion for windows 7, 8, 8.1, and 10 are all 6 so we really only need to check for the minor version
; but we use a procedure input here so its not hard coded so can be changed in case we want to test for other versions
osvi\dwOSVersionInfoSize = SizeOf(OSVERSIONINFOEX)
osvi\dwMajorVersion = 6
osvi\dwMinorVersion = 1
;wversion\dwMinorVersion = 0 for Windows Vista, and Windows Server 2008
;wversion\dwMinorVersion = 1 for Windows 7, and Windows Server 2008 R2
;wversion\dwMinorVersion = 2 for Windows 8, and Windows Server 2012
;wversion\dwMinorVersion = 3 for Windows 8.1, and Windows Server 2012 R2
;wversion\dwMinorVersion = 4 for Windows 10
osvi\wProductType = prodtype ; #VER_NT_SERVER ; or #VER_NT_WORKSTATION depending on if we test for workstation or server
; for example:
; major/minor on windows server 2008 R2 is same as windows 7 workstation so we need to diffrentiate via prodtype variable input
; major/minor on Windows Server 2012 is same as Windows 8 workstation so we need to diffrentiate via prodtype variable input
; major/minor on Windows Server 2012 R2 is same as windows 8.1 workstation so we need to diffrentiate via prodtype variable input
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_MAJORVERSION, #VER_GREATER_EQUAL)
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_MINORVERSION, #VER_GREATER_EQUAL)
dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, #VER_PRODUCT_TYPE, #VER_EQUAL)
isorisnotos = VerifyVersionInfo(osvi, #VER_MAJORVERSION|#VER_MINORVERSION|#VER_PRODUCT_TYPE, dwlConditionMask)
; If the operating system this is run in satisfies the specified requirements the return value is a nonzero value.
; If the operating system this is run in does not satisfy the specified requirements the return value is zero
ProcedureReturn isorisnotos
EndProcedure
Debug IsWindows7OrGreater(#VER_NT_WORKSTATION)
So, if someone could check it out and see how it works out for windows 8 and 8.1 .... don't have access to a windows 8 machine right now, waiting for a new hard drive to arrive for it.
thanks
The world and human nature was screwed up before I was born. It's not my fault and I'm just stuck with trying to deal with the mess left behind, so don't blame me.
Re: Windows 8 and 8.1
I'll take it as a YES. But after all it was a rethorical question.luis wrote: Wasn't all this and more already stated in the thread, link included
VerifyVersionInfo() could be useful if you want to test for more than just the version/build, but if you just need the version number I think it's A LOT simpler to just call RtlGetVersion() -> http://www.purebasic.fr/english/viewtop ... 21#p431121
When called from PB in user mode (from ntdll.dll) RtlGetVersion() switches the current thread in kernel mode to jump to its actual implementation in kernel code (the real mode code is just a "stub" where the address of the real function inside ntoskrnl.exe is loaded).
At that point since MS have not yet considered to screw up the answers one can get from this family of functions the code inside the kernel retrieve the real OS version, not exactly from the internal kernel structures as one could hope because seeing the thread is originally coming from user mode it just uses the process environment block initialized at process creation, still containing for now the correct data (see OSMajorVersion, OSMinorVersion, OSBuildNumber from http://en.wikipedia.org/wiki/Process_Environment_Block).
As long you don't call GetVersionEx() which wraps RtlGetVersion() poisoning its result if Windows > 8 and go directly to the source instead, you should be safe for the time being and get a straight answer to the simple question: what is the OS version ?
About your questions:
I've tested it under win7 x64 and win8.1 x64 and it does seem to work compiled as 32 and 64 bits (after the correction below).smacker wrote: can someone test this for Windows 8 and and 8.1, and if you have the preview build of Windows 10 on that also?
There was an error in the prototypes.smacker wrote: It seems to work compiled 64 bit Windows 7, but does not work when compiled 32 bit in Windows 7 and VerifyVersionInfo comes back with error code 1150 (using GetLastError) which translates to "The specified program requires a newer version of Windows." so i'm not sure if thats because it does not work in 32 bit at all or there is something else odd going on. I haven't read anything yet which indicates its 64 bit only.
VerSetConditionMask() returns and unsigned quad so it worked under x64 where the default return type is a 64 bit integer, on x86 was truncated and you lost the upper 32 bits, so it was working with some flags (the ones using the lower 32 bits) and not with others.
Also you don't need to be so strict with .l and .b in both prototypes and code (but you can if you wish), you can just use the base integer type everywhere avoiding conversions back and forth until the values are assigned where it counts (with a transparent one time truncation like in the case of OSVERSIONINFOEX assignments).
Code: Select all
EnableExplicit
Prototype.i PVerifyVersionInfo (*lpVersionInfo, dwTypeMask, dwlConditionMask.q) : Global VerifyVersionInfo.PVerifyVersionInfo
Prototype.q PVerSetConditionMask (in_ULONGLONG_dwlConditionMask.q, in_DWORD_dwTypeBitMask, in_BYTE_dwConditionMask) : Global VerSetConditionMask.PVerSetConditionMask
Global Lib_Kernel32 = OpenLibrary(#PB_Any, "Kernel32.dll")
If IsLibrary(Lib_Kernel32)
CompilerIf (#PB_Compiler_Unicode = 1)
VerifyVersionInfo.PVerifyVersionInfo=GetFunction(Lib_Kernel32,"VerifyVersionInfoW")
CompilerElse
VerifyVersionInfo.PVerifyVersionInfo=GetFunction(Lib_Kernel32,"VerifyVersionInfoA")
CompilerEndIf
VerSetConditionMask.PVerSetConditionMask=GetFunction(Lib_Kernel32,"VerSetConditionMask")
EndIf
#VER_MINORVERSION = $0000001
#VER_MAJORVERSION = $0000002
#VER_BUILDNUMBER = $0000004
#VER_PLATFORMID = $0000008
#VER_SERVICEPACKMINOR = $0000010
#VER_SERVICEPACKMAJOR = $0000020
#VER_PRODUCT_TYPE = $0000080
#VER_SUITENAME = $0000040
#VER_EQUAL = 1 ; The current value must be equal to the specified value..
#VER_GREATER = 2 ; The current value must be greater than the specified value.
#VER_GREATER_EQUAL = 3 ; The current value must be greater than or equal to the specified value.
#VER_LESS = 4 ; The current value must be less than the specified value.
#VER_LESS_EQUAL = 5 ; The current value must be less than or equal to the specified value.
; for VerSetConditionMask function if dwTypeBitMask is #VER_SUITENAME the dwConditionMask parameter can be one of the following values.
#VER_AND = 6 ; All product suites specified in the wSuiteMask member must be present in the current system.
#VER_OR = 7 ; At least one of the specified product suites must be present in the current system.
Procedure.i TestOSVersion(major, minor, prodtype)
Protected osvi.OSVERSIONINFOEX
Protected dwlConditionMask.q
Protected isorisnotos
osvi\dwOSVersionInfoSize = SizeOf(OSVERSIONINFOEX)
osvi\dwMajorVersion = major
osvi\dwMinorVersion = minor
osvi\wProductType = prodtype ; #VER_NT_SERVER ; or #VER_NT_WORKSTATION depending on if we test for workstation or server
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MAJORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_MINORVERSION, #VER_EQUAL)
dwlConditionMask = VerSetConditionMask(dwlConditionMask, #VER_PRODUCT_TYPE, #VER_EQUAL)
isorisnotos = VerifyVersionInfo(@osvi, #VER_MAJORVERSION|#VER_MINORVERSION|#VER_PRODUCT_TYPE, dwlConditionMask)
ProcedureReturn isorisnotos
EndProcedure
Debug TestOSVersion(6, 1, #VER_NT_WORKSTATION) ; Windows 7
Debug TestOSVersion(6, 1, #VER_NT_SERVER) ; Windows 7
Debug TestOSVersion(6, 3, #VER_NT_WORKSTATION) ; Windows 8.1
Debug TestOSVersion(6, 3, #VER_NT_SERVER) ; Windows 8.1
Last edited by luis on Mon Nov 10, 2014 8:59 pm, edited 1 time in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review
Re: Windows 8 and 8.1
Thanks luis, that's great 

The world and human nature was screwed up before I was born. It's not my fault and I'm just stuck with trying to deal with the mess left behind, so don't blame me.
- Teddy Rogers
- User
- Posts: 98
- Joined: Sun Feb 23, 2014 2:05 am
- Location: Australia
- Contact:
Re: Windows 8 and 8.1
RtlGetVersion routine works fine as an alternative...
Ted.
Code: Select all
Procedure.s RtlGetVersion()
Protected RTL.OSVERSIONINFOEX ; RTL Structure
RTL\dwOSVersionInfoSize = SizeOf(RTL) ; The size, in bytes, of an RTL_OSVERSIONINFOEX structure
ntdll = OpenLibrary(#PB_Any,"ntdll.dll")
If ntdll
*RtlGetVersion = GetFunction(ntdll,"RtlGetVersion")
If *RtlGetVersion
CallFunctionFast(*RtlGetVersion, @RTL)
EndIf
CloseLibrary(ntdll)
EndIf
ProcedureReturn Str(RTL\dwMajorVersion) + "." + Str(RTL\dwMinorVersion) + "." + Str(RTL\dwBuildNumber)
EndProcedure
Debug RtlGetVersion()
Re: Windows 8 and 8.1
yes, RtlGetVersion() is ok to use but it should be noted that the RtlGetVersion() seems to only works properly "fully" when compiled unicode when using the OSVERSIONINFOEX structure. For example, in ansi compile the 'wProductType' return will always be 0 where in unicode compile the 'wProductType' will return as what the version product type actually is, for example, #VER_NT_WORKSTATION or #VER_NT_SERVER or #VER_NT_DOMAIN_CONTROLLER, for OS with the same version, for example, Windows 7 is version 6.1 and Windows Server 2008 R2 is version 6.1 also.
The world and human nature was screwed up before I was born. It's not my fault and I'm just stuck with trying to deal with the mess left behind, so don't blame me.