概要

Windows上でバージョン情報を取得する方法はいろいろありますが主な方法として以下の3種類の方法が考えられます。
APIマニフェスト互換モード備考
GetVersionEx API8.1以上を取得時には指定が必要依存Windows 95以上又はWindows NT 3.5以上で実行可能
Windows 8.1以降は非推奨だが10でも使用可能
VerfyVersionInfo API10以上を取得時には指定が必要非依存自身のWindowsのバージョンに対して上位か同一か下位といった判定しかできない
Windows 2000以上でのみ実行可能
RtlGetVersion API非依存依存DDK等をインストールしていない場合、ヘッダーファイルおよびライブラリが無い
Windows 2000以上でのみ実行可能
上表のマニフェストはマニフェストにより動作バージョンを明示することを意味します。
マニフェストを指定しない場合、Windows 8.1まで正常な答えが得られました。マニフェストを指定しない場合ではWindows 10ではWindows 8相当の答えが返ってきます。 上表の互換モードはexeファイルのプロパティで互換性で設定できる互換モードです。
このページではRtlGetVersion APIについて解説します。
以下に本プログラムを各Windowsで実行した例を示します。
Windows 2000 Service Pack 4 Windows XP Service Pack 3 Windows Vista Service Pack 2 Windows 7 Service Pack 1 Windows 8.1 Windows 10

Windowsの内部バージョン一覧

Windowsの内部バージョン一覧を以下に示します。
メンバー NT 3.1
Workstation
NT 3.5
Workstation
NT 3.51
Workstation
dwMajorVersion 3 3 3
dwMinorVersion 1 5 51
wProductType 1 1 1

メンバー NT 4.0
Workstation
95 98 98SE me
dwMajorVersion 4 4 4 4 4
dwMinorVersion 0 0 10 10 90
wProductType 1 0 0 0 0

メンバー 2000 XP 2003R2
dwMajorVersion 5 5 5
dwMinorVersion 0 1 2
wProductType 1 1 3

メンバー Vista 7 2008R2 8 8.1 2012 2012R2
dwMajorVersion 6 6 6 6 6 6 6
dwMinorVersion 0 1 1 2 3 2 3
wProductType 1 1 3 1 1 3 3

メンバー 10
dwMajorVersion 10
dwMinorVersion 0
wProductType 1

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

プロジェクトの作成

Win32プロジェクト Windowsアプリケーション

実行環境

Windows 10 Pro 64bit(Virtual Box上)
Windows 8.1 Enterprise 64bit
Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit
Windows 2000 Professional Service Pack 4(Virtual Box上)

プログラムソースの概要

RtlGetVersion APIはDDK等をインストールしないとヘッダーファイルやライブラリが使えません。またANSI版が存在しません。
上記の煩わしさを解消するためにGetVersion2関数を作成しました。

_tWinMain

GetVersion2関数を呼び出し、OSVERSIONINFOEX構造体にバージョン情報を取得しメッセージボックスに結果を表示します。

GetVersion2

LoadLibrary APIによりntdll.dllを読み込みます。
GetProcAddress APIによりntdll.dllのRtlGetVersion APIのポインタを取得します。
RtlGetVersion APIを呼び出し、バージョン情報をOSVERSIONINFOEXW構造体に取得します。
マルチバイトでコンパイルする場合は、OSVERSIONINFOEXW構造体のメンバーをOSVERSIONINFOEXAのメンバーにコピーします。
UNICODE文字列が保存されているOSVERSIONINFOEXW構造体のszCSDVersionメンバーの文字列を ANSIに変換してOSVERSIONINFOEXA構造体のszCSDVersionメンバーに代入します。
最後にFreeLibrary APIでntdll.dllを解放します。

プログラムソース

RtlGetVersion.cpp

//	RtlGetVersion APIを使用してWindowsのバージョン番号を取得する
//	RtlGetVersion APIをサポートしていない場合は、GetVersionEx APIを使用する
//	Visual C++ 2005/2008/2013 Unicode/マルチバイト

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

//	DLL内の関数へのポインタ型を定義
typedef void (WINAPI *RtlGetVersion_FUNC)(OSVERSIONINFOEXW*);

BOOL GetVersion2(OSVERSIONINFOEX* os);

int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPTSTR lpsCmdLine, int nCmdShow){
	TCHAR buf[256];
	OSVERSIONINFOEX os;
	if (GetVersion2(&os) == TRUE){

		_stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), _TEXT("MajorVersion %d\nMinorVersion %d\nBuild %d\n"),
			os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber);

		MessageBox(0, buf, _TEXT("Windows Version"), MB_OK);
	}
	else{
		MessageBox(0, _TEXT("RtlGetVersion APIがサポートされていません"), _TEXT("Error"), MB_OK);
	}
	return (int)0;
}

BOOL GetVersion2(OSVERSIONINFOEX* os){
	HMODULE hMod;
	RtlGetVersion_FUNC func;
#ifdef UNICODE
	OSVERSIONINFOEXW* osw = os;
#else
	OSVERSIONINFOEXW o;
	OSVERSIONINFOEXW* osw = &o;
#endif

	hMod = LoadLibrary(TEXT("ntdll.dll"));
	if (hMod){
		func = (RtlGetVersion_FUNC)GetProcAddress(hMod, "RtlGetVersion");
		if (func == 0){
			FreeLibrary(hMod);
			return FALSE;
		}
		ZeroMemory(osw, sizeof(*osw));
		osw->dwOSVersionInfoSize = sizeof(*osw);
		func(osw);
#ifndef	UNICODE
		os->dwBuildNumber = osw->dwBuildNumber;
		os->dwMajorVersion = osw->dwMajorVersion;
		os->dwMinorVersion = osw->dwMinorVersion;
		os->dwPlatformId = osw->dwPlatformId;
		os->dwOSVersionInfoSize = sizeof(*os);
		DWORD sz = sizeof(os->szCSDVersion);
		WCHAR* src = osw->szCSDVersion;
		unsigned char* dtc = (unsigned char*)os->szCSDVersion;
		while (*src)
			*dtc++ = (unsigned char)*src++;
		*dtc = '\0';
#endif

	}
	else
		return FALSE;
	FreeLibrary(hMod);
	return TRUE;
}

manifest.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
        <application> 
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows 10 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>

        </application> 
    </compatibility>
</assembly>

ソースファイルと実行ファイルのダウンロード

ダウンロード RtlGetVersion.zip(67.7kByte)
ZIPファイルに含まれるファイル
RtlGetVersion.cpp		C++ソースファイル
RtlGetVersion.exe	Visual C++ 2013(v120_xp)で作成した実行ファイル(Windows XP~Windows 10で実行可能)
RtlGetVersion2008.exe	Visual C++ 2008で上作成した実行ファイル(Windows 2000~Windows 10で実行可能)