Referring to Thread: thread102-1568664
and FAQ: faq102-3232
It seems with the different windows flavors that are out there that it is difficult to get a good comprehensive version identification. That can be from the logic, the number of them (hard to test all of them!) or for the fact it's so hard to test most of them. These large number of flavors makes the code very extensive as well.
I did some research and did some initial coding. The question is always how accurate it is.
Below is code relating to generic version identification.
I also came up with some more specific version code, eg. "Windows XP Professional" instead of "Windows XP". This relates to things before Vista (can't test Vista or W7, it uses a newer API call to differentiate those).
The code I have tests right on everything I have access to, but hopefully some efforts can be made to get something that is known to work right in all cases.
I'm waiting for the white paper entitled "Finding Employment in the Era of Occupational Irrelevancy
and FAQ: faq102-3232
It seems with the different windows flavors that are out there that it is difficult to get a good comprehensive version identification. That can be from the logic, the number of them (hard to test all of them!) or for the fact it's so hard to test most of them. These large number of flavors makes the code very extensive as well.
I did some research and did some initial coding. The question is always how accurate it is.
Below is code relating to generic version identification.
Code:
unit winver;
{ windows versioning unit. Generic versioning only. }
interface
uses windows;
const
{ suite identifiers }
VER_SUITE_WH_SERVER = $8000;
{ product type identifiers }
VER_NT_WORKSTATION = $01;
{ processor identifiers }
PROCESSOR_ARCHITECTURE_AMD64 = 9;
SM_SERVERR2 = 89;
type
TOSVersionInfoExA = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array[0..127] of AnsiChar; { Maintenance string for PSS usage }
wServicePackMajor: Word;
wServicePackMinor: Word;
wSuiteMask: Word;
wProductType: Byte;
wReserved: byte;
end;
TOSVersionInfoExW = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array[0..127] of WideChar; { Maintenance string for PSS usage }
wServicePackMajor: Word;
wServicePackMinor: Word;
wSuiteMask: Word;
wProductType: Byte;
wReserved: byte;
end;
TOSVersionInfoEx = TOSVersionInfoExA;
TWinVersion = (wvUnknown, wvw32s, wv95, wv95OSR2, wv98, wv98SE, wvNT,
wvME, wv2000, wvXP, wvHomeServer, wvXP64, wv2003, wv2003_r2,
wvVista, wv2008, wv7, wv2008_R2);
function GetExVersionExA(var lpVersionInformation: TOSVersionInfoExA): boolean; stdcall;
function GetExVersionExW(var lpVersionInformation: TOSVersionInfoExW): boolean; stdcall;
procedure GetWinVersion(var inver: TWinVersion);
implementation
var
SysInfo: TSystemInfo;
function GetExVersionExA(var lpVersionInformation: TOSVersionInfoExA): boolean; stdcall;
external 'Kernel32.dll' name 'GetVersionExA';
function GetExVersionExW(var lpVersionInformation: TOSVersionInfoExW): boolean; stdcall;
external 'Kernel32.dll' name 'GetVersionExW';
procedure Win9XHandle(ovinfo: TOSVersionInfoExA; var inver: TWinVersion);
{ handle logic for determining version of Win9X systems }
begin
if OvInfo.dwMajorVersion = 4 then
case OvInfo.dwMinorVersion of
0: begin
if OvInfo.szCSDVersion[1] in ['B', 'C'] then
inver := wv95OSR2
else
inver := wv95;
end;
10: begin
if OvInfo.szCSDVersion[1] = 'A' then
inver := Wv98SE
else
inver := wv98;
end;
90: inver := wvME;
end;
end;
procedure Win2003Handle(ovinfo: TOSVersionInfoExA; var inver: TWinVersion);
{ handle code for differentiating Win 2003 class OSes }
begin
if ovinfo.wSuiteMask = VER_SUITE_WH_SERVER then
inver := wvHomeServer
else
begin
if (ovinfo.wProductType = VER_NT_WORKSTATION) and
(SysInfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64) then
inver := wvXP64
else
if GetSystemMetrics(SM_SERVERR2) <> 0 then
inver := wv2003_R2
else
inver := wv2003;
end;
end;
procedure WinNTHandle(ovinfo: TOSVersionInfoExA; var inver: TWinVersion);
{ handle logic for determining version of WinNT systems }
begin
case ovinfo.dwMajorVersion of
3: inver := wvNT;
4: inver := wvNT;
5: case ovinfo.dwMinorVersion of
0: inver := wv2000;
1: inver := wvXP;
2: Win2003Handle(ovinfo, inver);
end;
6: case ovinfo.dwMinorVersion of
0: if ovinfo.wProductType = VER_NT_WORKSTATION then
inver := wvVista
else
inver := wv2008;
1: if ovinfo.wProductType = VER_NT_WORKSTATION then
inver := wv7
else
inver := wv2008_R2;
end;
end;
end;
procedure GetWinVersion(var inver: TWinVersion);
{ main versioning routine }
var
OsVerInfo: TOSVersionInfoExA;
begin
inver := wvUnknown;
OSVerInfo.dwOsVersionInfoSize := Sizeof(TOsVersionInfoExA);
if GetExVersionExA(OsVerInfo) then
case osVerInfo.dwPlatformId of
VER_PLATFORM_WIN32_NT: WinNTHandle(OSVerInfo, inver);
VER_PLATFORM_WIN32_WINDOWS: Win9xHandle(OsVerInfo, inver);
VER_PLATFORM_WIN32S: inver := wvw32s;
end;
end;
initialization
GetSystemInfo(SysInfo);
finalization
end.
I also came up with some more specific version code, eg. "Windows XP Professional" instead of "Windows XP". This relates to things before Vista (can't test Vista or W7, it uses a newer API call to differentiate those).
The code I have tests right on everything I have access to, but hopefully some efforts can be made to get something that is known to work right in all cases.
I'm waiting for the white paper entitled "Finding Employment in the Era of Occupational Irrelevancy