If you are programming with C++Builder, then you are programming for Microsoft Windows. In fact, since C++Builder will only generate 32-bit code, you are programming for 32-bit Windows specifically. Is that all you need to know?
There are several versions of 32-bit Windows, including Windows NT and Windows 95/98. With each of these different versions there are similar but different APIs, registry entries and file structures. Sometimes it is important for us to be able to determine which 32-bit version of Windows our program is running on.
There are two methods can be used to get operating system version information; the Windows API or the VCL. I will discuss the both the API and the VCL methods of obtaining operating system information in the following sections.
The example program for this article is called OSVERSION. We don’t show the code for the entire project here, but you can download it from our Web site at http://www.bridgespublishing.com. The program gets the operating system information and displays it in a Memo component.
The example program’s GetOSVersionAPI() function uses the Windows API function GetVersionInfoEx() to obtain the version information. Here is the code for the GetOSVersionAPI() function:
void __fastcall TMainForm::GetOSVersionAPI(TStrings *lines)
{
OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
bool success = GetVersionEx(&info);
if (!success)
{
lines->Add("Unable to get OS Version Info");
return;
}
lines->Add("Major Version: " +
String(info.dwMajorVersion));
lines->Add("Minor Version: " +
String(info.dwMinorVersion));
DWORD buildNumber = info.dwBuildNumber;
if (info.dwPlatformId ==
VER_PLATFORM_WIN32_WINDOWS)
buildNumber = LOWORD(buildNumber);
lines->Add("Build Number: " +
String(buildNumber));
String platform = "Unknown";
if (info.dwPlatformId == VER_PLATFORM_WIN32s)
platform = "Win32s";
else if (info.dwPlatformId ==
VER_PLATFORM_WIN32_WINDOWS)
{
if ((info.dwMajorVersion > 4) ||
((info.dwMajorVersion == 4) &&
(info.dwMinorVersion > 0)))
platform = "Windows 98";
else
platform = "windows 95";
}
else if (info.dwPlatformId ==
VER_PLATFORM_WIN32_NT)
platform = "Windows NT";
lines->Add("Platform: " + platform);
String csdVersion = info.szCSDVersion;
if (csdVersion.IsEmpty() &&
info.dwPlatformId == VER_PLATFORM_WIN32_NT)
csdVersion = "No Service Pack Installed";
lines->Add("CSDVersion: " + csdVersion);
}
As you can see, the first parameter of GetVersionInfoEx() is a pointer to an OSVERSIONINFO structure. The members of this structure are listed in Table A.
Table A: OSVERSIONINFO members
|
Member |
Description |
|
|
dwOSVersionInfoSize |
This size of the structure in
bytes. You must set this member before calling GetVersionInfoEx(). |
|
|
dwMajorVersion |
The major version number of
Windows operating system. |
|
|
dwMinorVersion |
The minor version number of
Windows operating system. |
|
|
dwBuildNumber |
The build number of the operating system for Windows
NT. For Windows 9x, the low order word of dwBuildNumber
is the build number. |
|
|
dwPlatformId |
A value representing the
Windows platform. |
|
|
|
Value |
Platform |
|
|
VER_PLATFORM_WIN32s |
Win32s on Windows 3.1. |
|
|
VER_PLATFORM_WIN32_WINDOWS |
Windows 9x. If the
dwMinorVersion is zero, then Windows 95, otherwise Windows 98. |
|
|
VER_PLATFORM_WIN32_NT |
Windows NT. |
|
szCSDVersion |
A null-terminated string that
indicates the latest installed Service Pack on Windows NT. If the string
is empty, no Service Pack has been installed. May contain arbitrary
information for Windows 9x. |
|
In the GetOSVersionAPI() function I create an instance of OSVERSIONINFO, zero the memory occupied by the structure and set the size of the structure in the dwOSVersionInfoSize member.
Next I call GetVersionInfoEx() passing it a pointer to the OSVERSIONINFO structure and the size of that structure. GetVersionInfoEx() returns a non-zero value if it is successful. I test for this and if GetVersionInfoEx() fails, I display a message to the user and exit the function. If GetVersionInfoEx() succeeds, I analyze the values of the OSVERSIONINFO data members and post the findings to a TMemo component on the main form.
If you are using the VCL in our program, then C++Builder has done some of the work for you. There are a series of variables, which are global in the Sysutils namespace and correspond directly to the data members of the OSVERSIONINFO structure. Those variables and the corresponding OSVERSIONINFO data member are listed in Table B.
Table B: VCL variables
|
VCL Variable |
OSVERSIONINFO Member |
|
Win32MajorVersion |
dwMajorVersion |
|
Win32MinorVersion |
dwMinorVersion |
|
Win32BuildNumber |
dwBuildNumber |
|
Win32Platform |
dwPlatformId |
|
Win32CSDVersion |
dwCSDVersion |
The example program’s GetOSVersionVCL() function uses these variables instead of OSVERSIONINFO and GetVersionEx(), but otherwise is identical to GetOSVersionAPI(). Here is the code for the GetOSVersionVCL() function:
void __fastcall TMainForm::GetOSVersionVCL(TStrings *lines)
{
lines->Add("Major Version: " +
String(Win32MajorVersion));
lines->Add("Minor Version: " +
String(Win32MinorVersion));
int buildNumber = Win32BuildNumber;
if (Win32Platform ==
VER_PLATFORM_WIN32_WINDOWS)
buildNumber = LOWORD(buildNumber);
lines->Add("Build Number: " +
String(buildNumber));
String platform = "Unknown";
if (Win32Platform == VER_PLATFORM_WIN32s)
platform = "Win32s";
else if (Win32Platform ==
VER_PLATFORM_WIN32_WINDOWS)
{
if ((Win32MajorVersion > 4) ||
((Win32MajorVersion == 4) &&
(Win32MinorVersion > 0)))
platform = "Windows 98";
else
platform = "windows 95";
}
else if (Win32Platform ==
VER_PLATFORM_WIN32_NT)
platform = "Windows NT";
lines->Add("Platform: " + platform);
if (Win32CSDVersion.IsEmpty() &&
Win32Platform == VER_PLATFORM_WIN32_NT)
lines->Add("CSDVersion:"
" No Service Pack Installed");
else
lines->Add("CSDVersion: " +
Win32CSDVersion);
}
Don’t underestimate how much coding these VCL variables can save you. If you need to call one function on Windows NT and another function on Windows 9x, simply use the Win32Platform variable. Nothing could be easier.