Skip to content
This repository has been archived by the owner on Jul 26, 2023. It is now read-only.

Commit

Permalink
Merge pull request #498 from qmfrederik/features/ntdll-rtlgetversion
Browse files Browse the repository at this point in the history
Add NTDll.RtlGetVersion
  • Loading branch information
AArnott authored Jul 12, 2020
2 parents 0ab1f24 + 91fedfa commit 9b2253f
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 5 deletions.
34 changes: 34 additions & 0 deletions src/Kernel32/Kernel32+OSPlatformId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright © .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace PInvoke
{
using System.Runtime.InteropServices;

/// <summary>
/// Contains the <see cref="OSPlatformId"/> nested type.
/// </summary>
public static partial class Kernel32
{
/// <summary>
/// The <see cref="OSPlatformId"/> structure contains operating system version information.
/// </summary>
public enum OSPlatformId
{
/// <summary>
/// The operating system is Microsoft Windows 3.1.
/// </summary>
VER_PLATFORM_WIN32s = 0,

/// <summary>
/// The operating system is Windows 95, Windows 98, or operating systems descended from them.
/// </summary>
VER_PLATFORM_WIN32_WINDOWS = 1,

/// <summary>
/// The operating system is Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003, Windows XP, or Windows 2000.
/// </summary>
VER_PLATFORM_WIN32_NT = 2,
}
}
}
60 changes: 60 additions & 0 deletions src/Kernel32/Kernel32+OSVERSIONINFO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright © .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace PInvoke
{
using System.Runtime.InteropServices;

/// <summary>
/// Contains the <see cref="OSVERSIONINFO"/> nested type.
/// </summary>
public static partial class Kernel32
{
/// <summary>
/// The <see cref="OSVERSIONINFO"/> structure contains operating system version information.
/// </summary>
/// <see href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfow"/>
public unsafe struct OSVERSIONINFO
{
/// <summary>
/// The size of the <see cref="OSVERSIONINFO"/> structure in bytes.
/// </summary>
public int dwOSVersionInfoSize;

/// <summary>
/// The major OS version.
/// </summary>
public int dwMajorVersion;

/// <summary>
/// The minor OS version.
/// </summary>
public int dwMinorVersion;

/// <summary>
/// The build number of the OS.
/// </summary>
public int dwBuildNumber;

/// <summary>
/// The OS platform.
/// </summary>
public OSPlatformId dwPlatformId;

/// <summary>
/// A null-terminated string, such as "Service Pack 3", that indicates the latest Service Pack installed on the system.
/// If no Service Pack has been installed, the string is empty.
/// </summary>
public fixed char szCSDVersion[128];

/// <summary>
/// Initializes a new instance of the <see cref="OSVERSIONINFO" /> struct
/// with <see cref="dwOSVersionInfoSize" /> set to the correct value.
/// </summary>
/// <returns>
/// A newly initialized instance of <see cref="OSVERSIONINFO"/>
/// </returns>
public static OSVERSIONINFO Create() => new OSVERSIONINFO { dwOSVersionInfoSize = sizeof(OSVERSIONINFO) };
}
}
}
8 changes: 5 additions & 3 deletions src/Kernel32/Kernel32+OSVERSIONINFOEX.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ public unsafe partial struct OSVERSIONINFOEX
public byte wReserved;

/// <summary>
/// Helper method to create <see cref="OSVERSIONINFOEX"/> with
/// the right pre-initialization for <see cref="dwOSVersionInfoSize"/>
/// Initializes a new instance of the <see cref="OSVERSIONINFOEX" /> struct
/// with <see cref="dwOSVersionInfoSize" /> set to the correct value.
/// </summary>
/// <returns>A newly initialzed instance of <see cref="OSVERSIONINFOEX"/></returns>
/// <returns>
/// A newly initialized instance of <see cref="OSVERSIONINFOEX"/>
/// </returns>
public static OSVERSIONINFOEX Create() => new OSVERSIONINFOEX { dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX) };
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/Kernel32/Kernel32+OS_TYPE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,23 @@ public static partial class Kernel32
/// </summary>
public enum OS_TYPE : byte
{
/// <summary>
/// The operating system is Windows 8, Windows 7, Windows Vista, Windows XP Professional, Windows XP Home Edition, or Windows 2000 Professional.
/// </summary>
VER_NT_WORKSTATION = 0x00000001,

/// <summary>
/// The system is a domain controller and the operating system is Windows Server 2012 , Windows Server 2008 R2,
/// Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
/// </summary>
VER_NT_DOMAIN_CONTROLLER = 0x00000002,

/// <summary>
/// The operating system is Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
/// </summary>
/// <remarks>
/// Note that a server that is also a domain controller is reported as <see cref="VER_NT_DOMAIN_CONTROLLER"/>, not <see cref="VER_NT_SERVER"/>.
/// </remarks>
VER_NT_SERVER = 0x00000003
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Kernel32/Kernel32+PRODUCT_SUITE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public enum PRODUCT_SUITE : short
/// <summary>
/// Windows Home Server is installed.
/// </summary>
VER_SUITE_WH_SERVER = unchecked((short)0x00008000)
VER_SUITE_WH_SERVER = unchecked((short)0x00008000),
}
}
}
13 changes: 13 additions & 0 deletions src/Kernel32/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ PInvoke.Kernel32.FileSystemFlags.FILE_SUPPORTS_USN_JOURNAL = 33554432 -> PInvoke
PInvoke.Kernel32.FileSystemFlags.FILE_UNICODE_ON_DISK = 4 -> PInvoke.Kernel32.FileSystemFlags
PInvoke.Kernel32.FileSystemFlags.FILE_VOLUME_IS_COMPRESSED = 32768 -> PInvoke.Kernel32.FileSystemFlags
PInvoke.Kernel32.FileSystemFlags.FILE_VOLUME_QUOTAS = 32 -> PInvoke.Kernel32.FileSystemFlags
PInvoke.Kernel32.OSPlatformId
PInvoke.Kernel32.OSPlatformId.VER_PLATFORM_WIN32_NT = 2 -> PInvoke.Kernel32.OSPlatformId
PInvoke.Kernel32.OSPlatformId.VER_PLATFORM_WIN32_WINDOWS = 1 -> PInvoke.Kernel32.OSPlatformId
PInvoke.Kernel32.OSPlatformId.VER_PLATFORM_WIN32s = 0 -> PInvoke.Kernel32.OSPlatformId
PInvoke.Kernel32.OSVERSIONINFO
PInvoke.Kernel32.OSVERSIONINFO.OSVERSIONINFO() -> void
PInvoke.Kernel32.OSVERSIONINFO.dwBuildNumber -> int
PInvoke.Kernel32.OSVERSIONINFO.dwMajorVersion -> int
PInvoke.Kernel32.OSVERSIONINFO.dwMinorVersion -> int
PInvoke.Kernel32.OSVERSIONINFO.dwOSVersionInfoSize -> int
PInvoke.Kernel32.OSVERSIONINFO.dwPlatformId -> PInvoke.Kernel32.OSPlatformId
PInvoke.Kernel32.OSVERSIONINFO.szCSDVersion -> char*
PInvoke.Kernel32.PROCESSOR_NUMBER
PInvoke.Kernel32.PROCESSOR_NUMBER.Group -> ushort
PInvoke.Kernel32.PROCESSOR_NUMBER.Number -> byte
Expand Down Expand Up @@ -103,6 +115,7 @@ static PInvoke.Kernel32.GetNativeSystemInfo(System.IntPtr lpSystemInfo) -> void
static PInvoke.Kernel32.GetNativeSystemInfo(out PInvoke.Kernel32.SYSTEM_INFO lpSystemInfo) -> void
static PInvoke.Kernel32.GetVolumeInformation(string lpRootPathName, System.IntPtr lpVolumeNameBuffer, int nVolumeNameSize, out uint lpVolumeSerialNumber, out int lpMaximumComponentLength, out PInvoke.Kernel32.FileSystemFlags lpFileSystemFlags, System.IntPtr lpFileSystemNameBuffer, int nFileSystemNameSize) -> bool
static PInvoke.Kernel32.GetVolumeInformation(string lpRootPathName, char[] lpVolumeNameBuffer, int nVolumeNameSize, out uint lpVolumeSerialNumber, out int lpMaximumComponentLength, out PInvoke.Kernel32.FileSystemFlags lpFileSystemFlags, char[] lpFileSystemNameBuffer, int nFileSystemNameSize) -> bool
static PInvoke.Kernel32.OSVERSIONINFO.Create() -> PInvoke.Kernel32.OSVERSIONINFO
static PInvoke.Kernel32.ReadProcessMemory(PInvoke.Kernel32.SafeObjectHandle hProcess, System.IntPtr lpBaseAddress, System.IntPtr lpBuffer, System.UIntPtr nSize, out System.UIntPtr lpNumberOfBytesRead) -> bool
static PInvoke.Kernel32.SetFilePointer(PInvoke.Kernel32.SafeObjectHandle hFile, int lDistanceToMove, System.IntPtr lpDistanceToMoveHigh, System.IO.SeekOrigin dwMoveMethod) -> int
static PInvoke.Kernel32.SetFilePointer(PInvoke.Kernel32.SafeObjectHandle hFile, int lDistanceToMove, ref int? lpDistanceToMoveHigh, System.IO.SeekOrigin dwMoveMethod) -> int
Expand Down
24 changes: 23 additions & 1 deletion src/NTDll.Tests/NTDllFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using PInvoke;
using Xunit;
using static PInvoke.NTDll;
Expand Down Expand Up @@ -64,4 +63,27 @@ public unsafe void NtQueryInformationProcess_Test()
Assert.Equal(NTSTATUS.Code.STATUS_SUCCESS, result.Value);
}
}

[Fact]
public void RtlGetVersion_OSVERSIONINFO_Test()
{
var versionInfo = Kernel32.OSVERSIONINFO.Create();

Assert.Equal(NTSTATUS.Code.STATUS_SUCCESS, RtlGetVersion(ref versionInfo).Value);
Assert.Equal(Kernel32.OSPlatformId.VER_PLATFORM_WIN32_NT, versionInfo.dwPlatformId);
Assert.NotEqual(0, versionInfo.dwMajorVersion);
Assert.NotEqual(0, versionInfo.dwBuildNumber);
}

[Fact]
public unsafe void RtlGetVersion_OSVERSIONINFOEX_Test()
{
var versionInfoEx = Kernel32.OSVERSIONINFOEX.Create();

Assert.Equal(NTSTATUS.Code.STATUS_SUCCESS, RtlGetVersion((Kernel32.OSVERSIONINFO*)&versionInfoEx).Value);
Assert.Equal(2, versionInfoEx.dwPlatformId); // VER_PLATFORM_WIN32_NT
Assert.NotEqual(0, versionInfoEx.dwMajorVersion);
Assert.NotEqual(0, versionInfoEx.dwBuildNumber);
Assert.True(Enum.IsDefined(typeof(Kernel32.OS_TYPE), versionInfoEx.wProductType), $"Unexpected OS_TYPE value: 0x{(int)versionInfoEx.wProductType:X}");
}
}
17 changes: 17 additions & 0 deletions src/NTDll/NTDll.Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright © .NET Foundation and Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace PInvoke
{
/// <content>
/// Methods and nested types that are not strictly P/Invokes but provide
/// a slightly higher level of functionality to ease calling into native code.
/// </content>
public static partial class NTDll
{
// This is where you define methods that assist in calling P/Invoke methods.
// For example, if a P/Invoke method requires allocating unmanaged memory
// and freeing it up after the call, a helper method in this file would
// make "P/Invoking" for most callers much easier and is a welcome addition.
}
}
14 changes: 14 additions & 0 deletions src/NTDll/NTDll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ public static unsafe extern NTSTATUS NtQueryInformationProcess(
int ProcessInformationLength,
out int ReturnLength);

/// <summary>
/// The <see cref="RtlGetVersion(Kernel32.OSVERSIONINFO*)"/> routine returns version information about the currently running operating system.
/// </summary>
/// <param name="versionInformation">
/// A <see cref="Kernel32.OSVERSIONINFO"/> structure that contains the version information about the currently running operating system.
/// </param>
/// <returns>
/// <see cref="RtlGetVersion(Kernel32.OSVERSIONINFO*)"/> returns <see cref="NTSTATUS.Code.STATUS_SUCCESS"/>.
/// </returns>
/// <seealso href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion"/>
[DllImport(nameof(NTDll), SetLastError = true)]
public static unsafe extern NTSTATUS RtlGetVersion(
[Friendly(FriendlyFlags.Bidirectional)] Kernel32.OSVERSIONINFO* versionInformation);

/// <summary>
/// The NtClose routine closes an object handle.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/NTDll/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ PInvoke.NTDll.PROCESS_BASIC_INFORMATION.Reserved2b -> void*
PInvoke.NTDll.PROCESS_BASIC_INFORMATION.Reserved3 -> void*
PInvoke.NTDll.PROCESS_BASIC_INFORMATION.UniqueProcessId -> void*
static PInvoke.NTDll.NtQueryInformationProcess(PInvoke.Kernel32.SafeObjectHandle ProcessHandle, PInvoke.NTDll.PROCESSINFOCLASS ProcessInformationClass, System.IntPtr ProcessInformation, int ProcessInformationLength, out int ReturnLength) -> PInvoke.NTSTATUS
static PInvoke.NTDll.RtlGetVersion(System.IntPtr versionInformation) -> PInvoke.NTSTATUS
static PInvoke.NTDll.RtlGetVersion(ref PInvoke.Kernel32.OSVERSIONINFO versionInformation) -> PInvoke.NTSTATUS
static extern PInvoke.NTDll.NtQueryInformationProcess(PInvoke.Kernel32.SafeObjectHandle ProcessHandle, PInvoke.NTDll.PROCESSINFOCLASS ProcessInformationClass, void* ProcessInformation, int ProcessInformationLength, out int ReturnLength) -> PInvoke.NTSTATUS
static extern PInvoke.NTDll.RtlGetVersion(PInvoke.Kernel32.OSVERSIONINFO* versionInformation) -> PInvoke.NTSTATUS

0 comments on commit 9b2253f

Please sign in to comment.