From f0782ababa73a22b59ca90206bdd380acc7ceed4 Mon Sep 17 00:00:00 2001 From: Vatsan Madhavan Date: Sat, 12 Oct 2019 10:52:45 -0700 Subject: [PATCH 1/3] Add support for RtlVerifyVersionInfo --- src/Kernel32/Kernel32+OSVERSIONINFOEX.cs | 83 ++++++++++++++++++++ src/Kernel32/Kernel32+OS_TYPE.cs | 21 ++++++ src/Kernel32/Kernel32+PRODUCT_SUITE.cs | 96 ++++++++++++++++++++++++ src/Kernel32/Kernel32+VER_CONDITION.cs | 64 ++++++++++++++++ src/Kernel32/Kernel32+VER_MASK.cs | 61 +++++++++++++++ src/Kernel32/Kernel32.cs | 96 ++++++++++++++++++++++++ src/NTDll/NTDll.cs | 25 ++++++ 7 files changed, 446 insertions(+) create mode 100644 src/Kernel32/Kernel32+OSVERSIONINFOEX.cs create mode 100644 src/Kernel32/Kernel32+OS_TYPE.cs create mode 100644 src/Kernel32/Kernel32+PRODUCT_SUITE.cs create mode 100644 src/Kernel32/Kernel32+VER_CONDITION.cs create mode 100644 src/Kernel32/Kernel32+VER_MASK.cs diff --git a/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs b/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs new file mode 100644 index 00000000..bbe479a1 --- /dev/null +++ b/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs @@ -0,0 +1,83 @@ +// Copyright (c) All 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; + + /// + /// Contains the nested type. + /// + public static partial class Kernel32 + { + /// + /// The RTL_OSVERSIONINFOEXW structure contains operating system version information. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public partial struct OSVERSIONINFOEX + { + /// + /// The size, in bytes, of an RTL_OSVERSIONINFOEXW structure. + /// This member must be set before the structure is used with RtlGetVersion. + /// + public int dwOSVersionInfoSize; + + /// + /// The major version number of the operating system. For example, for Windows 2000, the major version number is five. + /// + public int dwMajorVersion; + + /// + /// The minor version number of the operating system. For example, for Windows 2000, the minor version number is zero + /// + public int dwMinorVersion; + + /// + /// The build number of the operating system. + /// + public int dwBuildNumber; + + /// + /// The operating system platform. For Win32 on NT-based operating systems, RtlGetVersion returns the value + /// VER_PLATFORM_WIN32_NT. + /// + public int dwPlatformId; + + /// + /// The service-pack version string. This member contains a null-terminated string, such as "Service Pack 3", which + /// indicates the latest service pack installed on the system. If no service pack is installed, RtlGetVersion might not + /// initialize this string. Initialize szCSDVersion to zero (empty string) before the call to RtlGetVersion. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCSDVersion; + + /// + /// The major version number of the latest service pack installed on the system. For example, for Service Pack 3, + /// the major version number is three. If no service pack has been installed, the value is zero. + /// + public short wServicePackMajor; + + /// + /// The minor version number of the latest service pack installed on the system. For example, for Service Pack 3, + /// the minor version number is zero. + /// + public short wServicePackMinor; + + /// + /// The product suites available on the system. This member is set to zero or to the bitwise OR of one or more of + /// the values. + /// + public PRODUCT_SUITE wSuiteMask; + + /// + /// The product type. This member contains additional information about the system. + /// + public OS_TYPE wProductType; + + /// + /// Reserved for future use. + /// + public byte wReserved; + } + } +} diff --git a/src/Kernel32/Kernel32+OS_TYPE.cs b/src/Kernel32/Kernel32+OS_TYPE.cs new file mode 100644 index 00000000..3399f348 --- /dev/null +++ b/src/Kernel32/Kernel32+OS_TYPE.cs @@ -0,0 +1,21 @@ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace PInvoke +{ + /// + /// Contains the nested type. + /// + public static partial class Kernel32 + { + /// + /// The product type enumeration + /// + public enum OS_TYPE : byte + { + VER_NT_WORKSTATION = 0x00000001, + VER_NT_DOMAIN_CONTROLLER = 0x00000002, + VER_NT_SERVER = 0x00000003 + } + } +} \ No newline at end of file diff --git a/src/Kernel32/Kernel32+PRODUCT_SUITE.cs b/src/Kernel32/Kernel32+PRODUCT_SUITE.cs new file mode 100644 index 00000000..d640ac44 --- /dev/null +++ b/src/Kernel32/Kernel32+PRODUCT_SUITE.cs @@ -0,0 +1,96 @@ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace PInvoke +{ + using System; + + /// + /// Contains the nested type + /// + public static partial class Kernel32 + { + /// + /// The product suites available on the system. + /// + [Flags] + public enum PRODUCT_SUITE : short + { + /// + /// Microsoft BackOffice components are installed. + /// + VER_SUITE_BACKOFFICE = 0x00000004, + + /// + /// Windows Server 2003, Web Edition is installed. + /// + VER_SUITE_BLADE = 0x00000400, + + /// + /// Windows Server 2003, Compute Cluster Edition is installed. + /// + VER_SUITE_COMPUTE_SERVER = 0x00004000, + + /// + /// Windows Server 2008 Datacenter, Windows Server 2003, Datacenter Edition, or Windows 2000 Datacenter Server is installed. + /// + VER_SUITE_DATACENTER = 0x00000080, + + /// + /// Windows Server 2008 Enterprise, Windows Server 2003, Enterprise Edition, or Windows 2000 Advanced Server is installed. + /// + VER_SUITE_ENTERPRISE = 0x00000002, + + /// + /// Windows XP Embedded is installed. + /// + VER_SUITE_EMBEDDEDNT = 0x00000040, + + /// + /// Windows Vista Home Premium, Windows Vista Home Basic, or Windows XP Home Edition is installed. + /// + VER_SUITE_PERSONAL = 0x00000200, + + /// + /// Remote Desktop is supported, but only one interactive session is supported. + /// This value is set unless the system is running in application server mode. + /// + VER_SUITE_SINGLEUSERTS = 0x00000100, + + /// + /// Microsoft Small Business Server was once installed on the system, but may have been upgraded to another version of Windows. + /// + /// + /// You should not rely solely on the VER_SUITE_SMALLBUSINESS flag to determine whether Small Business Server is currently installed. + /// Both this flag and the VER_SUITE_SMALLBUSINESS_RESTRICTED flag are set when this product suite is installed. If you upgrade this + /// installation to Windows Server, Standard Edition, the VER_SUITE_SMALLBUSINESS_RESTRICTED flag is cleared, but the + /// VER_SUITE_SMALLBUSINESS flag remains set, which, in this case, indicates that Small Business Server was previously installed on + /// this system. If this installation is further upgraded to Windows Server, Enterprise Edition, the VER_SUITE_SMALLBUSINESS flag + /// remains set. + /// + VER_SUITE_SMALLBUSINESS = 0x00000001, + + /// + /// Microsoft Small Business Server is installed with the restrictive client license in force. + /// For more information about this flag bit, see the remarks for flag. + /// + VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020, + + /// + /// Windows Storage Server 2003 R2 or Windows Storage Server 2003 is installed. + /// + VER_SUITE_STORAGE_SERVER = 0x00002000, + + /// + /// Terminal Services is installed. This value is always set. If VER_SUITE_TERMINAL is set but VER_SUITE_SINGLEUSERTS is not set, + /// the operating system is running in application server mode. + /// + VER_SUITE_TERMINAL = 0x00000010, + + /// + /// Windows Home Server is installed. + /// + VER_SUITE_WH_SERVER = unchecked((short)0x00008000) + } + } +} diff --git a/src/Kernel32/Kernel32+VER_CONDITION.cs b/src/Kernel32/Kernel32+VER_CONDITION.cs new file mode 100644 index 00000000..9c656cd2 --- /dev/null +++ b/src/Kernel32/Kernel32+VER_CONDITION.cs @@ -0,0 +1,64 @@ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace PInvoke +{ + /// + /// Contains the nested type + /// + public static partial class Kernel32 + { + /// + /// The operator to be used for the comparison. The VerifyVersionInfo function uses this operator to compare a specified + /// attribute value to the corresponding value for the currently running system. + /// + /// + /// For all values of dwTypeBitMask other than VER_SUITENAME, this parameter can be one of the following values: + /// - + /// - + /// - + /// - + /// - + /// If dwTypeBitMask is VER_SUITENAME, this parameter can be one of the following values: + /// - + /// - + /// + public enum VER_CONDITION : byte + { + /// + /// The current value must be equal to the specified value. + /// + VER_EQUAL = 1, + + /// + /// The current value must be greater than the specified value. + /// + VER_GREATER = 2, + + /// + /// The current value must be greater than or equal to the specified value. + /// + VER_GREATER_EQUAL = 3, + + /// + /// The current value must be less than the specified value. + /// + VER_LESS = 4, + + /// + /// The current value must be less than or equal to the specified value. + /// + VER_LESS_EQUAL = 5, + + /// + /// All product suites specified in the wSuiteMask member must be present in the current system. + /// + VER_AND = 6, + + /// + /// At least one of the specified product suites must be present in the current system. + /// + VER_OR = 7 + } + } +} diff --git a/src/Kernel32/Kernel32+VER_MASK.cs b/src/Kernel32/Kernel32+VER_MASK.cs new file mode 100644 index 00000000..3514f2ee --- /dev/null +++ b/src/Kernel32/Kernel32+VER_MASK.cs @@ -0,0 +1,61 @@ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace PInvoke +{ + using System; + + /// + /// Contains the nested type. + /// + public static partial class Kernel32 + { + /// + /// A mask that indicates the member of the structure whose comparison operator is being set. + /// This value corresponds to one of the bits specified in the dwTypeMask parameter for the VerifyVersionInfo function. + /// + [Flags] + public enum VER_MASK : int + { + /// + /// dwBuildNumber + /// + VER_BUILDNUMBER = 0x0000004, + + /// + /// dwBuildNumber + /// + VER_MAJORVERSION = 0x0000002, + + /// + /// dwMinorVersion + /// + VER_MINORVERSION = 0x0000001, + + /// + /// dwPlatformId + /// + VER_PLATFORMID = 0x0000008, + + /// + /// wProductType + /// + VER_PRODUCT_TYPE = 0x0000080, + + /// + /// wServicePackMajor + /// + VER_SERVICEPACKMAJOR = 0x0000020, + + /// + /// wServicePackMinor + /// + VER_SERVICEPACKMINOR = 0x0000010, + + /// + /// wSuiteMask + /// + VER_SUITENAME = 0x0000040 + } + } +} diff --git a/src/Kernel32/Kernel32.cs b/src/Kernel32/Kernel32.cs index d90c9cdf..1eb760e3 100644 --- a/src/Kernel32/Kernel32.cs +++ b/src/Kernel32/Kernel32.cs @@ -542,6 +542,102 @@ public static extern unsafe SafeObjectHandle CreateMutex( [DllImport(api_ms_win_core_errorhandling_l1_1_1, SetLastError = true)] public static extern void SetLastError(uint dwErrCode); + /// + /// Sets the bits of a 64-bit value to indicate the comparison operator to use for a specified operating system version + /// attribute. This function is used to build the dwlConditionMask parameter of the VerifyVersionInfo function. + /// + /// A value to be passed as the dwlConditionMask parameter of the VerifyVersionInfo function. + /// The function stores the comparison information in the bits of this variable. Before the first call to , + /// initialize this variable to zero. For subsequent calls, pass in the variable used in the previous call. + /// A mask that indicates the member of the structure whose comparison operator + /// is being set. This value corresponds to one of the bits specified in the dwTypeMask parameter for the + /// VerifyVersionInfo function + /// The operator to be used for the comparison. The VerifyVersionInfo function uses this + /// operator to compare a specified attribute value to the corresponding value for the currently running system. + /// The function returns the condition mask value. + [DllImport(api_ms_win_core_sysinfo_l1_2_0)] + public static extern long VerSetConditionMask(long ConditionMask, VER_MASK TypeMask, VER_CONDITION Condition); + + /// + /// Compares a set of operating system version requirements to the corresponding values for the currently + /// running version of the system.This function is subject to manifest-based behavior. + /// + /// + /// A pointer to an OSVERSIONINFOEX structure containing the operating system version requirements to compare. The + /// parameter indicates the members of this structure that contain information to compare.You must set the + /// member of this structure to Marshal.SizeOf(typeof(OSVERSIONINFOEX)). You must + /// also specify valid data for the members indicated by . The function ignores structure members for which the + /// corresponding bit is not set + /// + /// A mask that indicates the members of the structure to be tested. + /// The type of comparison to be used for each member being compared. To build this value, + /// call the function once for each member being compared. + /// + /// + /// If the currently running operating system satisfies the specified requirements, the return value is a nonzero value. + /// + /// + /// If the current system does not satisfy the requirements, the return value is zero and returns . + /// + /// + /// If the function fails, the return value is zero and returns an error code other than . + /// + /// + /// + /// + /// The VerifyVersionInfo function retrieves version information about the currently running operating system and compares it to the valid + /// members of the structure. This enables you to easily determine the presence of a required set of + /// operating system version conditions. It is preferable to use rather than + /// calling the GetVersionEx function to perform your own comparisons. + /// + /// + /// Typically, returns a nonzero value only if all specified tests succeed. + /// However, major, minor, and service pack versions are tested in a hierarchical manner because the operating system version is a combination of + /// these values. If a condition exists for the major version, it supersedes the conditions specified for minor version and service pack version. + /// (You cannot test for major version greater than 5 and minor version less than or equal to 1. If you specify such a test, the function will + /// change the request to test for a minor version greater than 1 because it is performing a greater than operation on the major version.) + /// + /// + /// The function tests these values in this order: major version, minor version, and service pack version.The function continues testing values while + /// they are equal, and stops when one of the values does not meet the specified condition.For example, if you test for a system greater than or + /// equal to version 5.1 service pack 1, the test succeeds if the current version is 6.0. (The major version is greater than the specified version, + /// so the testing stops.) In the same way, if you test for a system greater than or equal to version 5.1 service pack 1, the test succeeds if the + /// current version is 5.2. (The minor version is greater than the specified versions, so the testing stops.) However, if you test for a system greater + /// than or equal to version 5.1 service pack 1, the test fails if the current version is 5.0 service pack 2. (The minor version is not greater than + /// the specified version, so the testing stops.) + /// + /// + /// To verify a range of system versions, you must call twice.For example, to verify + /// that the system version is greater than 5.0 but less than or equal to 5.1, first call to + /// test that the major version is 5 and the minor version is greater than 0, then call + /// again to test that the major version is 5 and the minor version is less than or equal to 1. + /// + /// + /// Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. + /// This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating + /// system platform or version number, test for the presence of the feature itself. + /// + /// + /// To verify whether the current operating system is either the Media Center or Tablet PC version of Windows, call GetSystemMetrics. + /// + /// + /// Windows 10: + /// returns false when called by applications that do not have a + /// compatibility manifest for Windows 8.1 or Windows 10 if the parameter is set so that it specifies + /// Windows 8.1 or Windows 10, even when the current operating system version is Windows 8.1 or Windows 10. Specifically, + /// has the following behavior: + /// + /// If the application has no manifest, behaves as + /// if the operation system version is Windows 8 (6.2). + /// If the application has a manifest that contains the GUID that corresponds to Windows 8.1, + /// behaves as if the operation system version is Windows 8.1 (6.3). + /// If the application has a manifest that contains the GUID that corresponds to Windows 10, + /// behaves as if the operation system version is Windows 10 (10.0). + /// + /// + [DllImport(nameof(Kernel32))] + public static extern NTSTATUS VerifyVersionInfo(ref OSVERSIONINFOEX lpVersionInformation, VER_MASK dwTypeMask, long dwlConditionMask); + /// /// Closes a file search handle opened by the FindFirstFile, FindFirstFileEx, FindFirstFileNameW, /// FindFirstFileNameTransactedW, FindFirstFileTransacted, FindFirstStreamTransactedW, or FindFirstStreamW functions. diff --git a/src/NTDll/NTDll.cs b/src/NTDll/NTDll.cs index 13a8968e..42f6a1c4 100644 --- a/src/NTDll/NTDll.cs +++ b/src/NTDll/NTDll.cs @@ -42,6 +42,31 @@ public static extern unsafe NTSTATUS NtOpenSection( Kernel32.ACCESS_MASK desiredAccess, [Friendly(FriendlyFlags.In)] OBJECT_ATTRIBUTES* objectAttributes); + /// + /// The RtlVerifyVersionInfo routine compares a specified set of operating system version requirements to the + /// corresponding attributes of the currently running version of the operating system. + /// + /// Pointer to an structure that specifies the + /// operating system version requirements to compare to the corresponding attributes of the currently running + /// version of the operating system. + /// Specifies which members of VersionInfo to compare with the corresponding attributes of + /// the currently running version of the operating system. + /// Specifies how to compare each VersionInfo member. To set the value of ConditionMask, + /// a caller should use the function. + /// + /// when the specified version matches the currently running version of the operating system. + /// when the input parameters are not valid. + /// when the specified version does not match the currently running version of the operating system. + /// + /// + /// See remarks in . + /// + /// Unmanifested applications that call are not + /// suspectible to version-lies by the OS. + /// + [DllImport(nameof(NTDll))] + public static extern NTSTATUS RtlVerifyVersionInfo(ref Kernel32.OSVERSIONINFOEX VersionInfo, Kernel32.VER_MASK TypeMask, long ConditionMask); + /// /// The NtClose routine closes an object handle. /// From 9b73950ccacac67f2bfb3e1f93cb05951d9d6637 Mon Sep 17 00:00:00 2001 From: Vatsan Madhavan Date: Sat, 12 Oct 2019 14:28:31 -0700 Subject: [PATCH 2/3] Add public API's to PublicAPI.Unshipped.txt --- src/Kernel32/PublicAPI.Unshipped.txt | 52 +++++++++++++++++++++++++++- src/NTDll/PublicAPI.Unshipped.txt | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/Kernel32/PublicAPI.Unshipped.txt b/src/Kernel32/PublicAPI.Unshipped.txt index 47887927..2cb484ba 100644 --- a/src/Kernel32/PublicAPI.Unshipped.txt +++ b/src/Kernel32/PublicAPI.Unshipped.txt @@ -1,3 +1,51 @@ +PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_EQUAL = 1 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_GREATER = 2 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_GREATER_EQUAL = 3 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_LESS = 4 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_LESS_EQUAL = 5 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_AND = 6 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_CONDITION.VER_OR = 7 -> PInvoke.Kernel32.VER_CONDITION +PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_BUILDNUMBER = 4 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_MAJORVERSION = 2 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_MINORVERSION = 1 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_PLATFORMID = 8 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_PRODUCT_TYPE = 128 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_SERVICEPACKMAJOR = 32 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_SERVICEPACKMINOR = 16 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.VER_MASK.VER_SUITENAME = 64 -> PInvoke.Kernel32.VER_MASK +PInvoke.Kernel32.OS_TYPE +PInvoke.Kernel32.OS_TYPE.VER_NT_WORKSTATION = 1 -> PInvoke.Kernel32.OS_TYPE +PInvoke.Kernel32.OS_TYPE.VER_NT_DOMAIN_CONTROLLER = 2 -> PInvoke.Kernel32.OS_TYPE +PInvoke.Kernel32.OS_TYPE.VER_NT_SERVER = 3 -> PInvoke.Kernel32.OS_TYPE +PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_BACKOFFICE = 4 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_BLADE = 1024 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_COMPUTE_SERVER = 16384 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_DATACENTER = 128 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_ENTERPRISE = 2 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_EMBEDDEDNT = 64 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_PERSONAL = 512 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_SINGLEUSERTS = 256 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_SMALLBUSINESS = 1 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_SMALLBUSINESS_RESTRICTED = 32 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_STORAGE_SERVER = 8192 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_TERMINAL = 16 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_WH_SERVER = -32768 -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.OSVERSIONINFOEX +PInvoke.Kernel32.OSVERSIONINFOEX.OSVERSIONINFOEX() -> void +PInvoke.Kernel32.OSVERSIONINFOEX.dwOSVersionInfoSize -> int +PInvoke.Kernel32.OSVERSIONINFOEX.dwMajorVersion -> int +PInvoke.Kernel32.OSVERSIONINFOEX.dwMinorVersion -> int +PInvoke.Kernel32.OSVERSIONINFOEX.dwBuildNumber -> int +PInvoke.Kernel32.OSVERSIONINFOEX.dwPlatformId -> int +PInvoke.Kernel32.OSVERSIONINFOEX.szCSDVersion -> string +PInvoke.Kernel32.OSVERSIONINFOEX.wServicePackMajor -> short +PInvoke.Kernel32.OSVERSIONINFOEX.wServicePackMinor -> short +PInvoke.Kernel32.OSVERSIONINFOEX.wSuiteMask -> PInvoke.Kernel32.PRODUCT_SUITE +PInvoke.Kernel32.OSVERSIONINFOEX.wProductType -> PInvoke.Kernel32.OS_TYPE +PInvoke.Kernel32.OSVERSIONINFOEX.wReserved -> byte PInvoke.Kernel32.STARTUPINFO.Desktop.get -> string PInvoke.Kernel32.STARTUPINFO.Title.get -> string PInvoke.Kernel32.STARTUPINFO.hStdError -> System.IntPtr @@ -17,4 +65,6 @@ static PInvoke.Kernel32.GetStartupInfo(ref PInvoke.Kernel32.STARTUPINFO lpStartu static extern PInvoke.Kernel32.GetProcessId(System.IntPtr Process) -> int static extern PInvoke.Kernel32.GetStartupInfo(PInvoke.Kernel32.STARTUPINFO* lpStartupInfo) -> void static extern PInvoke.Kernel32.SetLastError(uint dwErrCode) -> void -static extern PInvoke.Kernel32.GetProcessTimes(PInvoke.Kernel32.SafeObjectHandle handle, out PInvoke.Kernel32.FILETIME creation, out PInvoke.Kernel32.FILETIME exit, out PInvoke.Kernel32.FILETIME kernel, out PInvoke.Kernel32.FILETIME user) -> bool \ No newline at end of file +static extern PInvoke.Kernel32.GetProcessTimes(PInvoke.Kernel32.SafeObjectHandle handle, out PInvoke.Kernel32.FILETIME creation, out PInvoke.Kernel32.FILETIME exit, out PInvoke.Kernel32.FILETIME kernel, out PInvoke.Kernel32.FILETIME user) -> bool +static extern PInvoke.Kernel32.VerSetConditionMask(long ConditionMask, PInvoke.Kernel32.VER_MASK TypeMask, PInvoke.Kernel32.VER_CONDITION Condition) -> long +static extern PInvoke.Kernel32.VerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX lpVersionInformation, PInvoke.Kernel32.VER_MASK dwTypeMask, long dwlConditionMask) -> PInvoke.NTSTATUS diff --git a/src/NTDll/PublicAPI.Unshipped.txt b/src/NTDll/PublicAPI.Unshipped.txt index e69de29b..a5ab7eaf 100644 --- a/src/NTDll/PublicAPI.Unshipped.txt +++ b/src/NTDll/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +static extern PInvoke.NTDll.RtlVerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX VersionInfo, PInvoke.Kernel32.VER_MASK TypeMask, long ConditionMask) -> PInvoke.NTSTATUS From 5101d307e40f2e9ac4113fb1edf23e839b38a9e0 Mon Sep 17 00:00:00 2001 From: Vatsan Madhavan Date: Sun, 13 Oct 2019 16:23:35 -0700 Subject: [PATCH 3/3] Addressing PR Feedback --- src/Kernel32/Kernel32+OSVERSIONINFOEX.cs | 19 +++++++++++-- src/Kernel32/Kernel32+PRODUCT_SUITE.cs | 12 ++++---- src/Kernel32/Kernel32+VER_CONDITION.cs | 2 +- src/Kernel32/Kernel32+VER_MASK.cs | 2 +- src/Kernel32/Kernel32.cs | 35 +++++++++++++----------- src/Kernel32/PublicAPI.Unshipped.txt | 9 ++++-- src/NTDll/NTDll.cs | 11 +++++--- src/NTDll/PublicAPI.Unshipped.txt | 4 ++- 8 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs b/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs index bbe479a1..e32f40d8 100644 --- a/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs +++ b/src/Kernel32/Kernel32+OSVERSIONINFOEX.cs @@ -14,7 +14,7 @@ public static partial class Kernel32 /// The RTL_OSVERSIONINFOEXW structure contains operating system version information. /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public partial struct OSVERSIONINFOEX + public unsafe partial struct OSVERSIONINFOEX { /// /// The size, in bytes, of an RTL_OSVERSIONINFOEXW structure. @@ -48,8 +48,7 @@ public partial struct OSVERSIONINFOEX /// indicates the latest service pack installed on the system. If no service pack is installed, RtlGetVersion might not /// initialize this string. Initialize szCSDVersion to zero (empty string) before the call to RtlGetVersion. /// - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] - public string szCSDVersion; + public fixed char szCSDVersion[128]; /// /// The major version number of the latest service pack installed on the system. For example, for Service Pack 3, @@ -78,6 +77,20 @@ public partial struct OSVERSIONINFOEX /// Reserved for future use. /// public byte wReserved; + + /// + /// Helper method to create with + /// the right pre-initialization for + /// + /// A newly initialzed instance of + public static OSVERSIONINFOEX Create() => new OSVERSIONINFOEX + { +#if NETSTANDARD1_3_ORLATER + dwOSVersionInfoSize = Marshal.SizeOf() +#else + dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) +#endif + }; } } } diff --git a/src/Kernel32/Kernel32+PRODUCT_SUITE.cs b/src/Kernel32/Kernel32+PRODUCT_SUITE.cs index d640ac44..08547836 100644 --- a/src/Kernel32/Kernel32+PRODUCT_SUITE.cs +++ b/src/Kernel32/Kernel32+PRODUCT_SUITE.cs @@ -61,11 +61,11 @@ public enum PRODUCT_SUITE : short /// Microsoft Small Business Server was once installed on the system, but may have been upgraded to another version of Windows. /// /// - /// You should not rely solely on the VER_SUITE_SMALLBUSINESS flag to determine whether Small Business Server is currently installed. - /// Both this flag and the VER_SUITE_SMALLBUSINESS_RESTRICTED flag are set when this product suite is installed. If you upgrade this - /// installation to Windows Server, Standard Edition, the VER_SUITE_SMALLBUSINESS_RESTRICTED flag is cleared, but the - /// VER_SUITE_SMALLBUSINESS flag remains set, which, in this case, indicates that Small Business Server was previously installed on - /// this system. If this installation is further upgraded to Windows Server, Enterprise Edition, the VER_SUITE_SMALLBUSINESS flag + /// You should not rely solely on the flag to determine whether Small Business Server is currently installed. + /// Both this flag and the flag are set when this product suite is installed. If you upgrade this + /// installation to Windows Server, Standard Edition, the flag is cleared, but the + /// flag remains set, which, in this case, indicates that Small Business Server was previously installed on + /// this system. If this installation is further upgraded to Windows Server, Enterprise Edition, the flag /// remains set. /// VER_SUITE_SMALLBUSINESS = 0x00000001, @@ -82,7 +82,7 @@ public enum PRODUCT_SUITE : short VER_SUITE_STORAGE_SERVER = 0x00002000, /// - /// Terminal Services is installed. This value is always set. If VER_SUITE_TERMINAL is set but VER_SUITE_SINGLEUSERTS is not set, + /// Terminal Services is installed. This value is always set. If is set but is not set, /// the operating system is running in application server mode. /// VER_SUITE_TERMINAL = 0x00000010, diff --git a/src/Kernel32/Kernel32+VER_CONDITION.cs b/src/Kernel32/Kernel32+VER_CONDITION.cs index 9c656cd2..d4451072 100644 --- a/src/Kernel32/Kernel32+VER_CONDITION.cs +++ b/src/Kernel32/Kernel32+VER_CONDITION.cs @@ -9,7 +9,7 @@ namespace PInvoke public static partial class Kernel32 { /// - /// The operator to be used for the comparison. The VerifyVersionInfo function uses this operator to compare a specified + /// The operator to be used for the comparison. The function uses this operator to compare a specified /// attribute value to the corresponding value for the currently running system. /// /// diff --git a/src/Kernel32/Kernel32+VER_MASK.cs b/src/Kernel32/Kernel32+VER_MASK.cs index 3514f2ee..c066db30 100644 --- a/src/Kernel32/Kernel32+VER_MASK.cs +++ b/src/Kernel32/Kernel32+VER_MASK.cs @@ -12,7 +12,7 @@ public static partial class Kernel32 { /// /// A mask that indicates the member of the structure whose comparison operator is being set. - /// This value corresponds to one of the bits specified in the dwTypeMask parameter for the VerifyVersionInfo function. + /// This value corresponds to one of the bits specified in the dwTypeMask parameter for the function. /// [Flags] public enum VER_MASK : int diff --git a/src/Kernel32/Kernel32.cs b/src/Kernel32/Kernel32.cs index 1eb760e3..caf82aae 100644 --- a/src/Kernel32/Kernel32.cs +++ b/src/Kernel32/Kernel32.cs @@ -544,15 +544,15 @@ public static extern unsafe SafeObjectHandle CreateMutex( /// /// Sets the bits of a 64-bit value to indicate the comparison operator to use for a specified operating system version - /// attribute. This function is used to build the dwlConditionMask parameter of the VerifyVersionInfo function. + /// attribute. This function is used to build the dwlConditionMask parameter of the function. /// - /// A value to be passed as the dwlConditionMask parameter of the VerifyVersionInfo function. + /// A value to be passed as the dwlConditionMask parameter of the function. /// The function stores the comparison information in the bits of this variable. Before the first call to , /// initialize this variable to zero. For subsequent calls, pass in the variable used in the previous call. /// A mask that indicates the member of the structure whose comparison operator /// is being set. This value corresponds to one of the bits specified in the dwTypeMask parameter for the - /// VerifyVersionInfo function - /// The operator to be used for the comparison. The VerifyVersionInfo function uses this + /// function + /// The operator to be used for the comparison. The function uses this /// operator to compare a specified attribute value to the corresponding value for the currently running system. /// The function returns the condition mask value. [DllImport(api_ms_win_core_sysinfo_l1_2_0)] @@ -585,13 +585,13 @@ public static extern unsafe SafeObjectHandle CreateMutex( /// /// /// - /// The VerifyVersionInfo function retrieves version information about the currently running operating system and compares it to the valid + /// The function retrieves version information about the currently running operating system and compares it to the valid /// members of the structure. This enables you to easily determine the presence of a required set of - /// operating system version conditions. It is preferable to use rather than + /// operating system version conditions. It is preferable to use rather than /// calling the GetVersionEx function to perform your own comparisons. /// /// - /// Typically, returns a nonzero value only if all specified tests succeed. + /// Typically, returns a nonzero value only if all specified tests succeed. /// However, major, minor, and service pack versions are tested in a hierarchical manner because the operating system version is a combination of /// these values. If a condition exists for the major version, it supersedes the conditions specified for minor version and service pack version. /// (You cannot test for major version greater than 5 and minor version less than or equal to 1. If you specify such a test, the function will @@ -607,9 +607,9 @@ public static extern unsafe SafeObjectHandle CreateMutex( /// the specified version, so the testing stops.) /// /// - /// To verify a range of system versions, you must call twice.For example, to verify - /// that the system version is greater than 5.0 but less than or equal to 5.1, first call to - /// test that the major version is 5 and the minor version is greater than 0, then call + /// To verify a range of system versions, you must call twice.For example, to verify + /// that the system version is greater than 5.0 but less than or equal to 5.1, first call to + /// test that the major version is 5 and the minor version is greater than 0, then call /// again to test that the major version is 5 and the minor version is less than or equal to 1. /// /// @@ -622,21 +622,24 @@ public static extern unsafe SafeObjectHandle CreateMutex( /// /// /// Windows 10: - /// returns false when called by applications that do not have a + /// returns false when called by applications that do not have a /// compatibility manifest for Windows 8.1 or Windows 10 if the parameter is set so that it specifies /// Windows 8.1 or Windows 10, even when the current operating system version is Windows 8.1 or Windows 10. Specifically, - /// has the following behavior: + /// has the following behavior: /// - /// If the application has no manifest, behaves as + /// If the application has no manifest, behaves as /// if the operation system version is Windows 8 (6.2). - /// If the application has a manifest that contains the GUID that corresponds to Windows 8.1, + /// If the application has a manifest that contains the GUID that corresponds to Windows 8.1, /// behaves as if the operation system version is Windows 8.1 (6.3). - /// If the application has a manifest that contains the GUID that corresponds to Windows 10, + /// If the application has a manifest that contains the GUID that corresponds to Windows 10, /// behaves as if the operation system version is Windows 10 (10.0). /// /// [DllImport(nameof(Kernel32))] - public static extern NTSTATUS VerifyVersionInfo(ref OSVERSIONINFOEX lpVersionInformation, VER_MASK dwTypeMask, long dwlConditionMask); + public static unsafe extern NTSTATUS VerifyVersionInfo( + [Friendly(FriendlyFlags.Bidirectional)] OSVERSIONINFOEX* lpVersionInformation, + VER_MASK dwTypeMask, + long dwlConditionMask); /// /// Closes a file search handle opened by the FindFirstFile, FindFirstFileEx, FindFirstFileNameW, diff --git a/src/Kernel32/PublicAPI.Unshipped.txt b/src/Kernel32/PublicAPI.Unshipped.txt index 2cb484ba..126f2090 100644 --- a/src/Kernel32/PublicAPI.Unshipped.txt +++ b/src/Kernel32/PublicAPI.Unshipped.txt @@ -35,12 +35,13 @@ PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_TERMINAL = 16 -> PInvoke.Kernel32.PRODU PInvoke.Kernel32.PRODUCT_SUITE.VER_SUITE_WH_SERVER = -32768 -> PInvoke.Kernel32.PRODUCT_SUITE PInvoke.Kernel32.OSVERSIONINFOEX PInvoke.Kernel32.OSVERSIONINFOEX.OSVERSIONINFOEX() -> void +static PInvoke.Kernel32.OSVERSIONINFOEX.Create() -> PInvoke.Kernel32.OSVERSIONINFOEX PInvoke.Kernel32.OSVERSIONINFOEX.dwOSVersionInfoSize -> int PInvoke.Kernel32.OSVERSIONINFOEX.dwMajorVersion -> int PInvoke.Kernel32.OSVERSIONINFOEX.dwMinorVersion -> int PInvoke.Kernel32.OSVERSIONINFOEX.dwBuildNumber -> int PInvoke.Kernel32.OSVERSIONINFOEX.dwPlatformId -> int -PInvoke.Kernel32.OSVERSIONINFOEX.szCSDVersion -> string +PInvoke.Kernel32.OSVERSIONINFOEX.szCSDVersion -> char* PInvoke.Kernel32.OSVERSIONINFOEX.wServicePackMajor -> short PInvoke.Kernel32.OSVERSIONINFOEX.wServicePackMinor -> short PInvoke.Kernel32.OSVERSIONINFOEX.wSuiteMask -> PInvoke.Kernel32.PRODUCT_SUITE @@ -67,4 +68,8 @@ static extern PInvoke.Kernel32.GetStartupInfo(PInvoke.Kernel32.STARTUPINFO* lpSt static extern PInvoke.Kernel32.SetLastError(uint dwErrCode) -> void static extern PInvoke.Kernel32.GetProcessTimes(PInvoke.Kernel32.SafeObjectHandle handle, out PInvoke.Kernel32.FILETIME creation, out PInvoke.Kernel32.FILETIME exit, out PInvoke.Kernel32.FILETIME kernel, out PInvoke.Kernel32.FILETIME user) -> bool static extern PInvoke.Kernel32.VerSetConditionMask(long ConditionMask, PInvoke.Kernel32.VER_MASK TypeMask, PInvoke.Kernel32.VER_CONDITION Condition) -> long -static extern PInvoke.Kernel32.VerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX lpVersionInformation, PInvoke.Kernel32.VER_MASK dwTypeMask, long dwlConditionMask) -> PInvoke.NTSTATUS +static extern PInvoke.Kernel32.VerifyVersionInfo(PInvoke.Kernel32.OSVERSIONINFOEX* lpVersionInformation, PInvoke.Kernel32.VER_MASK dwTypeMask, long dwlConditionMask) -> PInvoke.NTSTATUS +static PInvoke.Kernel32.VerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX lpVersionInformation, PInvoke.Kernel32.VER_MASK dwTypeMask, long dwlConditionMask) -> PInvoke.NTSTATUS +static PInvoke.Kernel32.VerifyVersionInfo(System.IntPtr lpVersionInformation, PInvoke.Kernel32.VER_MASK dwTypeMask, long dwlConditionMask) -> PInvoke.NTSTATUS + + diff --git a/src/NTDll/NTDll.cs b/src/NTDll/NTDll.cs index 42f6a1c4..42e484cf 100644 --- a/src/NTDll/NTDll.cs +++ b/src/NTDll/NTDll.cs @@ -43,7 +43,7 @@ public static extern unsafe NTSTATUS NtOpenSection( [Friendly(FriendlyFlags.In)] OBJECT_ATTRIBUTES* objectAttributes); /// - /// The RtlVerifyVersionInfo routine compares a specified set of operating system version requirements to the + /// The routine compares a specified set of operating system version requirements to the /// corresponding attributes of the currently running version of the operating system. /// /// Pointer to an structure that specifies the @@ -59,13 +59,16 @@ public static extern unsafe NTSTATUS NtOpenSection( /// when the specified version does not match the currently running version of the operating system. /// /// - /// See remarks in . + /// See remarks in . /// - /// Unmanifested applications that call are not + /// Unmanifested applications that call are not /// suspectible to version-lies by the OS. /// [DllImport(nameof(NTDll))] - public static extern NTSTATUS RtlVerifyVersionInfo(ref Kernel32.OSVERSIONINFOEX VersionInfo, Kernel32.VER_MASK TypeMask, long ConditionMask); + public static unsafe extern NTSTATUS RtlVerifyVersionInfo( + [Friendly(FriendlyFlags.Bidirectional)]Kernel32.OSVERSIONINFOEX* VersionInfo, + Kernel32.VER_MASK TypeMask, + long ConditionMask); /// /// The NtClose routine closes an object handle. diff --git a/src/NTDll/PublicAPI.Unshipped.txt b/src/NTDll/PublicAPI.Unshipped.txt index a5ab7eaf..9723d3c0 100644 --- a/src/NTDll/PublicAPI.Unshipped.txt +++ b/src/NTDll/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ -static extern PInvoke.NTDll.RtlVerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX VersionInfo, PInvoke.Kernel32.VER_MASK TypeMask, long ConditionMask) -> PInvoke.NTSTATUS +static extern PInvoke.NTDll.RtlVerifyVersionInfo(PInvoke.Kernel32.OSVERSIONINFOEX* VersionInfo, PInvoke.Kernel32.VER_MASK TypeMask, long ConditionMask) -> PInvoke.NTSTATUS +static PInvoke.NTDll.RtlVerifyVersionInfo(ref PInvoke.Kernel32.OSVERSIONINFOEX VersionInfo, PInvoke.Kernel32.VER_MASK TypeMask, long ConditionMask) -> PInvoke.NTSTATUS +static PInvoke.NTDll.RtlVerifyVersionInfo(System.IntPtr VersionInfo, PInvoke.Kernel32.VER_MASK TypeMask, long ConditionMask) -> PInvoke.NTSTATUS