mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
507 lines
21 KiB
507 lines
21 KiB
/* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
|
|
namespace Alphaleonis.Win32
|
|
{
|
|
/// <summary>Static class providing access to information about the operating system under which the assembly is executing.</summary>
|
|
public static class OperatingSystem
|
|
{
|
|
#region OperatingSystem Name Enum
|
|
|
|
/// <summary>A set of flags that describe the named Windows versions.</summary>
|
|
/// <remarks>The values of the enumeration are ordered. A later released operating system version has a higher number, so comparisons between named versions are meaningful.</remarks>
|
|
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Os")]
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Os")]
|
|
public enum EnumOsName
|
|
{
|
|
/// <summary>A Windows version earlier than Windows 2000.</summary>
|
|
Earlier = -1,
|
|
|
|
/// <summary>Windows 2000 (Server or Professional).</summary>
|
|
Windows2000 = 0,
|
|
|
|
/// <summary>Windows XP.</summary>
|
|
WindowsXP = 1,
|
|
|
|
/// <summary>Windows Server 2003.</summary>
|
|
WindowsServer2003 = 2,
|
|
|
|
/// <summary>Windows Vista.</summary>
|
|
WindowsVista = 3,
|
|
|
|
/// <summary>Windows Server 2008.</summary>
|
|
WindowsServer2008 = 4,
|
|
|
|
/// <summary>Windows 7.</summary>
|
|
Windows7 = 5,
|
|
|
|
/// <summary>Windows Server 2008 R2.</summary>
|
|
WindowsServer2008R2 = 6,
|
|
|
|
/// <summary>Windows 8.</summary>
|
|
Windows8 = 7,
|
|
|
|
/// <summary>Windows Server 2012.</summary>
|
|
WindowsServer2012 = 8,
|
|
|
|
/// <summary>Windows 8.1.</summary>
|
|
Windows81 = 9,
|
|
|
|
/// <summary>Windows Server 2012 R2</summary>
|
|
WindowsServer2012R2 = 10,
|
|
|
|
/// <summary>Windows 10</summary>
|
|
Windows10 = 11,
|
|
|
|
/// <summary>Windows Server</summary>
|
|
WindowsServer = 12,
|
|
|
|
/// <summary>A later version of Windows than currently installed.</summary>
|
|
Later = 65535
|
|
}
|
|
|
|
#endregion // OperatingSystem Name Enum
|
|
|
|
#region ProcessorArchitecture Name enum
|
|
|
|
/// <summary>A set of flags to indicate the current processor architecture for which the operating system is targeted and running.</summary>
|
|
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Pa")]
|
|
[SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32")]
|
|
public enum EnumProcessorArchitecture
|
|
{
|
|
/// <summary>PROCESSOR_ARCHITECTURE_INTEL
|
|
/// <para>The system is running a 32-bit version of Windows.</para>
|
|
/// </summary>
|
|
X86 = 0,
|
|
|
|
/// <summary>PROCESSOR_ARCHITECTURE_IA64
|
|
/// <para>The system is running on a Itanium processor.</para>
|
|
/// </summary>
|
|
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ia")]
|
|
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Ia")]
|
|
IA64 = 6,
|
|
|
|
/// <summary>PROCESSOR_ARCHITECTURE_AMD64
|
|
/// <para>The system is running a 64-bit version of Windows.</para>
|
|
/// </summary>
|
|
X64 = 9,
|
|
|
|
/// <summary>PROCESSOR_ARCHITECTURE_UNKNOWN
|
|
/// <para>Unknown architecture.</para>
|
|
/// </summary>
|
|
Unknown = 65535
|
|
}
|
|
|
|
#endregion // ProcessorArchitecture Name enum
|
|
|
|
|
|
#region Properties
|
|
|
|
#region IsServer
|
|
|
|
private static bool _isServer;
|
|
|
|
/// <summary>Gets a value indicating whether the operating system is a server operating system.</summary>
|
|
/// <value><see langword="true"/> if the current operating system is a server operating system; otherwise, <see langword="false"/>.</value>
|
|
public static bool IsServer
|
|
{
|
|
get
|
|
{
|
|
if (_servicePackVersion == null)
|
|
UpdateData();
|
|
return _isServer;
|
|
}
|
|
}
|
|
|
|
#endregion // IsServer
|
|
|
|
#region IsWow64Process
|
|
|
|
private static bool? _isWow64Process;
|
|
|
|
/// <summary>Gets a value indicating whether the current process is running under WOW64.</summary>
|
|
/// <value><see langword="true"/> if the current process is running under WOW64; otherwise, <see langword="false"/>.</value>
|
|
public static bool IsWow64Process
|
|
{
|
|
get
|
|
{
|
|
if (_isWow64Process == null)
|
|
{
|
|
bool value;
|
|
IntPtr processHandle = Process.GetCurrentProcess().Handle;
|
|
|
|
if (!NativeMethods.IsWow64Process(processHandle, out value))
|
|
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
|
|
|
// A pointer to a value that is set to TRUE if the process is running under WOW64.
|
|
// If the process is running under 32-bit Windows, the value is set to FALSE.
|
|
// If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE.
|
|
|
|
_isWow64Process = value;
|
|
}
|
|
|
|
return (bool) _isWow64Process;
|
|
}
|
|
}
|
|
|
|
#endregion // IsWow64Process
|
|
|
|
#region OSVersion
|
|
|
|
private static Version _osVersion;
|
|
|
|
/// <summary>Gets the numeric version of the operating system.</summary>
|
|
/// <value>The numeric version of the operating system.</value>
|
|
public static Version OSVersion
|
|
{
|
|
get
|
|
{
|
|
if (_osVersion == null)
|
|
UpdateData();
|
|
|
|
return _osVersion;
|
|
}
|
|
}
|
|
|
|
#endregion // OSVersion
|
|
|
|
#region VersionName
|
|
|
|
private static EnumOsName _enumOsName = EnumOsName.Later;
|
|
|
|
/// <summary>Gets the named version of the operating system.</summary>
|
|
/// <value>The named version of the operating system.</value>
|
|
public static EnumOsName VersionName
|
|
{
|
|
get
|
|
{
|
|
if (_servicePackVersion == null)
|
|
UpdateData();
|
|
|
|
return _enumOsName;
|
|
}
|
|
}
|
|
|
|
#endregion // VersionName
|
|
|
|
#region ProcessorArchitecture
|
|
|
|
private static EnumProcessorArchitecture _processorArchitecture;
|
|
|
|
/// <summary>Gets the processor architecture for which the operating system is targeted.</summary>
|
|
/// <value>The processor architecture for which the operating system is targeted.</value>
|
|
/// <remarks>If running under WOW64 this will return a 32-bit processor. Use <see cref="IsWow64Process"/> to determine if this is the case.</remarks>
|
|
public static EnumProcessorArchitecture ProcessorArchitecture
|
|
{
|
|
get
|
|
{
|
|
if (_servicePackVersion == null)
|
|
UpdateData();
|
|
|
|
return _processorArchitecture;
|
|
}
|
|
}
|
|
|
|
#endregion // ProcessorArchitecture
|
|
|
|
#region ServicePackVersion
|
|
|
|
private static Version _servicePackVersion;
|
|
|
|
/// <summary>Gets the version of the service pack currently installed on the operating system.</summary>
|
|
/// <value>The version of the service pack currently installed on the operating system.</value>
|
|
/// <remarks>Only the <see cref="System.Version.Major"/> and <see cref="System.Version.Minor"/> fields are used.</remarks>
|
|
public static Version ServicePackVersion
|
|
{
|
|
get
|
|
{
|
|
if (_servicePackVersion == null)
|
|
UpdateData();
|
|
|
|
return _servicePackVersion;
|
|
}
|
|
}
|
|
|
|
#endregion // ServicePackVersion
|
|
|
|
#endregion // Properties
|
|
|
|
#region Methods
|
|
|
|
#region IsAtLeast
|
|
|
|
/// <summary>Determines whether the operating system is of the specified version or later.</summary>
|
|
/// <returns><see langword="true"/> if the operating system is of the specified <paramref name="version"/> or later; otherwise, <see langword="false"/>.</returns>
|
|
/// <param name="version">The lowest version for which to return true.</param>
|
|
public static bool IsAtLeast(EnumOsName version)
|
|
{
|
|
return VersionName >= version;
|
|
}
|
|
|
|
/// <summary>Determines whether the operating system is of the specified version or later, allowing specification of a minimum service pack that must be installed on the lowest version.</summary>
|
|
/// <returns><see langword="true"/> if the operating system matches the specified <paramref name="version"/> with the specified service pack, or if the operating system is of a later version; otherwise, <see langword="false"/>.</returns>
|
|
/// <param name="version">The minimum required version.</param>
|
|
/// <param name="servicePackVersion">The major version of the service pack that must be installed on the minimum required version to return true. This can be 0 to indicate that no service pack is required.</param>
|
|
public static bool IsAtLeast(EnumOsName version, int servicePackVersion)
|
|
{
|
|
return IsAtLeast(version) && ServicePackVersion.Major >= servicePackVersion;
|
|
}
|
|
|
|
#endregion // IsAtLeast
|
|
|
|
#endregion // Methods
|
|
|
|
|
|
#region Private
|
|
|
|
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "RtlGetVersion")]
|
|
private static void UpdateData()
|
|
{
|
|
var verInfo = new NativeMethods.RTL_OSVERSIONINFOEXW();
|
|
|
|
// Needed to prevent: System.Runtime.InteropServices.COMException:
|
|
// The data area passed to a system call is too small. (Exception from HRESULT: 0x8007007A)
|
|
verInfo.dwOSVersionInfoSize = Marshal.SizeOf(verInfo);
|
|
|
|
var sysInfo = new NativeMethods.SYSTEM_INFO();
|
|
NativeMethods.GetNativeSystemInfo(ref sysInfo);
|
|
|
|
|
|
// RtlGetVersion returns STATUS_SUCCESS (0).
|
|
if (NativeMethods.RtlGetVersion(ref verInfo))
|
|
throw new Win32Exception(Marshal.GetLastWin32Error(), "Function RtlGetVersion() failed to retrieve the operating system information.");
|
|
|
|
|
|
_osVersion = new Version(verInfo.dwMajorVersion, verInfo.dwMinorVersion, verInfo.dwBuildNumber);
|
|
|
|
_processorArchitecture = (EnumProcessorArchitecture) sysInfo.wProcessorArchitecture;
|
|
_servicePackVersion = new Version(verInfo.wServicePackMajor, verInfo.wServicePackMinor);
|
|
_isServer = verInfo.wProductType == NativeMethods.VER_NT_DOMAIN_CONTROLLER || verInfo.wProductType == NativeMethods.VER_NT_SERVER;
|
|
|
|
|
|
// RtlGetVersion: https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910%28v=vs.85%29.aspx
|
|
|
|
// The following table summarizes the most recent operating system version numbers.
|
|
// Operating system Version number Other
|
|
// ================================================================================
|
|
// Windows 10 10.0 OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
|
|
// Windows Server 10.0 OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
|
|
// Windows 8.1 6.3 OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
|
|
// Windows Server 2012 R2 6.3 OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
|
|
// Windows 8 6.2 OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
|
|
// Windows Server 2012 6.2 OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
|
|
// Windows 7 6.1 OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
|
|
// Windows Server 2008 R2 6.1 OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
|
|
// Windows Server 2008 6.0 OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
|
|
// Windows Vista 6.0 OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
|
|
// Windows Server 2003 R2 5.2 GetSystemMetrics(SM_SERVERR2) != 0
|
|
// Windows Server 2003 5.2 GetSystemMetrics(SM_SERVERR2) == 0
|
|
// Windows XP 64-Bit Edition 5.2 (OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION) && (sysInfo.PaName == PaName.X64)
|
|
// Windows XP 5.1 Not applicable
|
|
// Windows 2000 5.0 Not applicable
|
|
|
|
|
|
// 10 == The lastest MajorVersion of Windows.
|
|
if (verInfo.dwMajorVersion > 10)
|
|
_enumOsName = EnumOsName.Later;
|
|
|
|
else
|
|
switch (verInfo.dwMajorVersion)
|
|
{
|
|
#region Version 10
|
|
|
|
case 10:
|
|
switch (verInfo.dwMinorVersion)
|
|
{
|
|
// Windows 10 or Windows Server
|
|
case 0:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION)
|
|
? EnumOsName.Windows10
|
|
: EnumOsName.WindowsServer;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
#endregion // Version 10
|
|
|
|
#region Version 6
|
|
|
|
case 6:
|
|
switch (verInfo.dwMinorVersion)
|
|
{
|
|
// Windows Vista or Windows Server 2008
|
|
case 0:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION)
|
|
? EnumOsName.WindowsVista
|
|
: EnumOsName.WindowsServer2008;
|
|
break;
|
|
|
|
// Windows 7 or Windows Server 2008 R2
|
|
case 1:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION)
|
|
? EnumOsName.Windows7
|
|
: EnumOsName.WindowsServer2008R2;
|
|
break;
|
|
|
|
// Windows 8 or Windows Server 2012
|
|
case 2:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION)
|
|
? EnumOsName.Windows8
|
|
: EnumOsName.WindowsServer2012;
|
|
break;
|
|
|
|
// Windows 8.1 or Windows Server 2012 R2
|
|
case 3:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION)
|
|
? EnumOsName.Windows81
|
|
: EnumOsName.WindowsServer2012R2;
|
|
break;
|
|
|
|
default:
|
|
_enumOsName = EnumOsName.Later;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
#endregion // Version 6
|
|
|
|
#region Version 5
|
|
|
|
case 5:
|
|
switch (verInfo.dwMinorVersion)
|
|
{
|
|
case 0:
|
|
_enumOsName = EnumOsName.Windows2000;
|
|
break;
|
|
|
|
case 1:
|
|
_enumOsName = EnumOsName.WindowsXP;
|
|
break;
|
|
|
|
case 2:
|
|
_enumOsName = (verInfo.wProductType == NativeMethods.VER_NT_WORKSTATION && _processorArchitecture == EnumProcessorArchitecture.X64)
|
|
? EnumOsName.WindowsXP
|
|
: (verInfo.wProductType != NativeMethods.VER_NT_WORKSTATION) ? EnumOsName.WindowsServer2003 : EnumOsName.Later;
|
|
break;
|
|
|
|
default:
|
|
_enumOsName = EnumOsName.Later;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
#endregion // Version 5
|
|
|
|
default:
|
|
_enumOsName = EnumOsName.Earlier;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#region P/Invoke members / NativeMethods
|
|
|
|
private static class NativeMethods
|
|
{
|
|
internal const short VER_NT_WORKSTATION = 1;
|
|
internal const short VER_NT_DOMAIN_CONTROLLER = 2;
|
|
internal const short VER_NT_SERVER = 3;
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
|
internal struct RTL_OSVERSIONINFOEXW
|
|
{
|
|
public int dwOSVersionInfoSize;
|
|
public readonly int dwMajorVersion;
|
|
public readonly int dwMinorVersion;
|
|
public readonly int dwBuildNumber;
|
|
public readonly int dwPlatformId;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
|
public readonly string szCSDVersion;
|
|
public readonly ushort wServicePackMajor;
|
|
public readonly ushort wServicePackMinor;
|
|
public readonly ushort wSuiteMask;
|
|
public readonly byte wProductType;
|
|
public readonly byte wReserved;
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
|
internal struct SYSTEM_INFO
|
|
{
|
|
public readonly ushort wProcessorArchitecture;
|
|
private readonly ushort wReserved;
|
|
public readonly uint dwPageSize;
|
|
public readonly IntPtr lpMinimumApplicationAddress;
|
|
public readonly IntPtr lpMaximumApplicationAddress;
|
|
public readonly IntPtr dwActiveProcessorMask;
|
|
public readonly uint dwNumberOfProcessors;
|
|
public readonly uint dwProcessorType;
|
|
public readonly uint dwAllocationGranularity;
|
|
public readonly ushort wProcessorLevel;
|
|
public readonly ushort wProcessorRevision;
|
|
}
|
|
|
|
|
|
/// <summary>The RtlGetVersion routine returns version information about the currently running operating system.</summary>
|
|
/// <returns>RtlGetVersion returns STATUS_SUCCESS.</returns>
|
|
/// <remarks>Available starting with Windows 2000.</remarks>
|
|
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule"), DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool RtlGetVersion([MarshalAs(UnmanagedType.Struct)] ref RTL_OSVERSIONINFOEXW lpVersionInformation);
|
|
|
|
|
|
/// <summary>Retrieves information about the current system to an application running under WOW64.
|
|
/// If the function is called from a 64-bit application, it is equivalent to the GetSystemInfo function.
|
|
/// </summary>
|
|
/// <returns>This function does not return a value.</returns>
|
|
/// <remarks>To determine whether a Win32-based application is running under WOW64, call the <see cref="IsWow64Process"/> function.</remarks>
|
|
/// <remarks>Minimum supported client: Windows XP [desktop apps | Windows Store apps]</remarks>
|
|
/// <remarks>Minimum supported server: Windows Server 2003 [desktop apps | Windows Store apps]</remarks>
|
|
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
|
|
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
|
|
internal static extern void GetNativeSystemInfo([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);
|
|
|
|
|
|
/// <summary>Determines whether the specified process is running under WOW64.</summary>
|
|
/// <returns>
|
|
/// If the function succeeds, the return value is a nonzero value.
|
|
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
|
/// </returns>
|
|
/// <remarks>Minimum supported client: Windows Vista, Windows XP with SP2 [desktop apps only]</remarks>
|
|
/// <remarks>Minimum supported server: Windows Server 2008, Windows Server 2003 with SP1 [desktop apps only]</remarks>
|
|
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
|
|
[DllImport("kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool IsWow64Process([In] IntPtr hProcess, [Out, MarshalAs(UnmanagedType.Bool)] out bool lpSystemInfo);
|
|
}
|
|
|
|
#endregion // P/Invoke members / NativeMethods
|
|
|
|
#endregion // Private
|
|
}
|
|
}
|
|
|