using System; using System.Runtime.InteropServices; using Vanara.InteropServices; using static Vanara.PInvoke.Crypt32; namespace Vanara.PInvoke { public static partial class AdvApi32 { /// public const string SRP_POLICY_APPX = "APPX"; /// public const string SRP_POLICY_DLL = "DLL"; /// public const string SRP_POLICY_EXE = "EXE"; /// public const string SRP_POLICY_MANAGEDINSTALLER = "MANAGEDINSTALLER"; /// public const string SRP_POLICY_MSI = "MSI"; /// public const string SRP_POLICY_NOV2 = "IGNORESRPV2"; /// public const string SRP_POLICY_SCRIPT = "SCRIPT"; /// public const string SRP_POLICY_SHELL = "SHELL"; /// public const string SRP_POLICY_WLDPCONFIGCI = "WLDPCONFIGCI"; /// public const string SRP_POLICY_WLDPMSI = "WLDPMSI"; /// public const string SRP_POLICY_WLDPSCRIPT = "WLDPSCRIPT"; private const int SAFER_MAX_HASH_SIZE = 64; /// The types of criteria considered when evaluating this structure. [PInvokeData("winsafer.h", MSDNShortId = "039a37a9-1744-4cff-919e-e0da50d7b291")] [Flags] public enum SAFER_CRITERIA { /// Check the code image path. SAFER_CRITERIA_IMAGEPATH = 0x00001, /// Check the code hash. SAFER_CRITERIA_IMAGEHASH = 0x00004, /// /// Check the Authenticode signature. If this value is used, either the hImageFileHandle member or the ImagePath member must be set. /// SAFER_CRITERIA_AUTHENTICODE = 0x00008, /// Check the URL of origin. SAFER_CRITERIA_URLZONE = 0x00010, /// Check the Windows NT image path. SAFER_CRITERIA_IMAGEPATH_NT = 0x01000, /// Check for a Windows Store app package. For use by Windows Store apps. SAFER_CRITERIA_APPX_PACKAGE = 0x00020, } /// [PInvokeData("winsafer.h")] public enum SAFER_LEVEL_CREATE_FLAGS { /// SAFER_LEVEL_OPEN = 1, } /// [PInvokeData("winsafer.h")] [Flags] public enum SAFER_LEVELID { /// /// Software cannot access certain resources, such as cryptographic keys and credentials, regardless of the user rights of the user. /// SAFER_LEVELID_CONSTRAINED = 0x10000, /// Software will not run, regardless of the user rights of the user. SAFER_LEVELID_DISALLOWED = 0x00000, /// Software user rights are determined by the user rights of the user. SAFER_LEVELID_FULLYTRUSTED = 0x40000, /// /// Allows programs to execute as a user that does not have Administrator or Power User user rights. Software can access /// resources accessible by normal users. /// SAFER_LEVELID_NORMALUSER = 0x20000, /// /// Allows programs to execute with access only to resources granted to open well-known groups, blocking access to Administrator /// and Power User privileges and personally granted rights. /// SAFER_LEVELID_UNTRUSTED = 0x01000, } /// The SAFER_OBJECT_INFO_CLASS enumeration type defines the type of information requested about a Safer object. /// The SAFER_OBJECT_INFO_CLASS enumeration type is used by the SaferGetLevelInformation function. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/ne-winsafer-_safer_object_info_class typedef enum // _SAFER_OBJECT_INFO_CLASS { SaferObjectLevelId, SaferObjectScopeId, SaferObjectFriendlyName, SaferObjectDescription, // SaferObjectBuiltin, SaferObjectDisallowed, SaferObjectDisableMaxPrivilege, SaferObjectInvertDeletedPrivileges, // SaferObjectDeletedPrivileges, SaferObjectDefaultOwner, SaferObjectSidsToDisable, SaferObjectRestrictedSidsInverted, // SaferObjectRestrictedSidsAdded, SaferObjectAllIdentificationGuids, SaferObjectSingleIdentification, SaferObjectExtendedError } SAFER_OBJECT_INFO_CLASS; [PInvokeData("winsafer.h", MSDNShortId = "31de9e42-6795-433a-937f-c4243e4961df")] public enum SAFER_OBJECT_INFO_CLASS { /// The LEVELID constant. [CorrespondingType(typeof(SAFER_LEVELID), CorrespondingAction.GetSet)] SaferObjectLevelId = 1, /// The user or machine scope. [CorrespondingType(typeof(SAFER_SCOPEID), CorrespondingAction.GetSet)] SaferObjectScopeId, /// The display name. [CorrespondingType(typeof(string), CorrespondingAction.GetSet)] SaferObjectFriendlyName, /// The description. [CorrespondingType(typeof(string), CorrespondingAction.GetSet)] SaferObjectDescription, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferObjectBuiltin, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferObjectDisallowed, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferObjectDisableMaxPrivilege, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferObjectInvertDeletedPrivileges, /// [CorrespondingType(typeof(TOKEN_PRIVILEGES), CorrespondingAction.Get)] SaferObjectDeletedPrivileges, /// [CorrespondingType(typeof(TOKEN_OWNER), CorrespondingAction.Get)] SaferObjectDefaultOwner, /// [CorrespondingType(typeof(TOKEN_GROUPS), CorrespondingAction.Get)] SaferObjectSidsToDisable, /// [CorrespondingType(typeof(TOKEN_GROUPS), CorrespondingAction.Get)] SaferObjectRestrictedSidsInverted, /// [CorrespondingType(typeof(TOKEN_GROUPS), CorrespondingAction.Get)] SaferObjectRestrictedSidsAdded, /// Queries for all levels. [CorrespondingType(typeof(IntPtr), CorrespondingAction.Get)] SaferObjectAllIdentificationGuids, /// Queries for a single additional rule. [CorrespondingType(typeof(IntPtr), CorrespondingAction.GetSet)] SaferObjectSingleIdentification, /// Queries for additional error codes set during rule processing. [CorrespondingType(typeof(Win32Error), CorrespondingAction.Get)] SaferObjectExtendedError, } /// The SAFER_POLICY_INFO_CLASS enumeration type defines the ways in which a policy may be queried. /// The SAFER_POLICY_INFO_CLASS enumeration type is used by the SaferGetPolicyInformation function. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/ne-winsafer-_safer_policy_info_class typedef enum // _SAFER_POLICY_INFO_CLASS { SaferPolicyLevelList, SaferPolicyEnableTransparentEnforcement, SaferPolicyDefaultLevel, // SaferPolicyEvaluateUserScope, SaferPolicyScopeFlags, SaferPolicyDefaultLevelFlags, SaferPolicyAuthenticodeEnabled } SAFER_POLICY_INFO_CLASS; [PInvokeData("winsafer.h", MSDNShortId = "e1438a9f-abca-463d-8a3a-3a820cba16e8")] public enum SAFER_POLICY_INFO_CLASS { /// The list of all levels defined in a policy. [CorrespondingType(typeof(uint[]), CorrespondingAction.GetSet)] SaferPolicyLevelList = 1, /// Determines whether DLL checking is enabled. [CorrespondingType(typeof(uint), CorrespondingAction.GetSet)] SaferPolicyEnableTransparentEnforcement, /// The default policy level. [CorrespondingType(typeof(SAFER_LEVELID), CorrespondingAction.GetSet)] SaferPolicyDefaultLevel, /// Determines whether user scope rules should be consulted during policy evaluation. [CorrespondingType(typeof(uint), CorrespondingAction.GetSet)] SaferPolicyEvaluateUserScope, /// Determines whether the policy is to skip members of the local administrators group. [CorrespondingType(typeof(uint), CorrespondingAction.GetSet)] SaferPolicyScopeFlags, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferPolicyDefaultLevelFlags, /// [CorrespondingType(typeof(uint), CorrespondingAction.Get)] SaferPolicyAuthenticodeEnabled, } /// The scope of the created level. [PInvokeData("winsafer.h")] public enum SAFER_SCOPEID { /// The scope of the created level is by computer. SAFER_SCOPEID_MACHINE = 1, /// The scope of the created level is by user. SAFER_SCOPEID_USER = 2, } /// Specifies the behavior of . [PInvokeData("winsafer.h", MSDNShortId = "39406331-3101-48f2-8b92-e049849b2b38")] [Flags] public enum SAFER_TOKEN_FLAGS { /// /// If the OutAccessToken parameter is not more restrictive than the InAccessToken parameter, the OutAccessToken parameter /// returns NULL. /// SAFER_TOKEN_NULL_IF_EQUAL = 1, /// /// The token specified by the InAccessToken parameter is compared with the token that would be created if the restrictions /// specified by the LevelHandle parameter were applied. The restricted token is not actually created. /// On output, the value of the lpReserved parameter specifies the result of the comparison. /// SAFER_TOKEN_COMPARE_ONLY = 2, /// /// If this flag is set, the system does not check AppLocker rules or apply Software Restriction Policies. For AppLocker, this /// flag disables checks for all four rule collections: Executable, Windows Installer, Script, and DLL. /// Set this flag when creating a setup program that must run extracted DLLs during installation. /// A token can be queried for existence of this flag by using GetTokenInformation. /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: AppLocker is not supported. /// SAFER_TOKEN_MAKE_INERT = 4, /// On output, the value of the lpReserved parameter specifies the set of flags used to create the restricted token. SAFER_TOKEN_WANT_FLAGS = 8, } /// /// The SaferCloseLevel function closes a SAFER_LEVEL_HANDLE that was opened by using the SaferIdentifyLevel function or the /// SaferCreateLevel function. /// /// The SAFER_LEVEL_HANDLE to be closed. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safercloselevel BOOL SaferCloseLevel( SAFER_LEVEL_HANDLE // hLevelHandle ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "8daffb35-5bb0-45b3-aff1-a8ea6a142ba5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferCloseLevel(SAFER_LEVEL_HANDLE hLevelHandle); /// The SaferComputeTokenFromLevel function restricts a token using restrictions specified by a SAFER_LEVEL_HANDLE. /// /// SAFER_LEVEL_HANDLE that contains the restrictions to place on the input token. Do not pass handles with a LevelId of /// SAFER_LEVELID_FULLYTRUSTED or SAFER_LEVELID_DISALLOWED to this function. This is because /// SAFER_LEVELID_FULLYTRUSTED is unrestricted and SAFER_LEVELID_DISALLOWED does not contain a token. /// /// /// Token to be restricted. If this parameter is NULL, the token of the current thread will be used. If the current thread /// does not contain a token, the token of the current process is used. /// /// The resulting restricted token. /// /// /// Specifies the behavior of the method. The value can be NULL or one or more of the following values combined by using a /// bitwise- OR operation. /// /// /// /// Value /// Meaning /// /// /// SAFER_TOKEN_NULL_IF_EQUAL 1 (0x1) /// /// If the OutAccessToken parameter is not more restrictive than the InAccessToken parameter, the OutAccessToken parameter returns NULL. /// /// /// /// SAFER_TOKEN_COMPARE_ONLY 2 (0x2) /// /// The token specified by the InAccessToken parameter is compared with the token that would be created if the restrictions specified /// by the LevelHandle parameter were applied. The restricted token is not actually created. On output, the value of the lpReserved /// parameter specifies the result of the comparison. /// /// /// /// SAFER_TOKEN_MAKE_INERT 4 (0x4) /// /// If this flag is set, the system does not check AppLocker rules or apply Software Restriction Policies. For AppLocker, this flag /// disables checks for all four rule collections: Executable, Windows Installer, Script, and DLL. Set this flag when creating a /// setup program that must run extracted DLLs during installation. A token can be queried for existence of this flag by using /// GetTokenInformation. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: AppLocker is not supported. /// /// /// /// SAFER_TOKEN_WANT_FLAGS 8 (0x8) /// On output, the value of the lpReserved parameter specifies the set of flags used to create the restricted token. /// /// /// /// /// /// If the SAFER_TOKEN_COMPARE_ONLY flag is set, this parameter, on output, specifies the result of the token comparison. The /// output value is an LPDWORD. A value of –1 indicates that the resulting token would be less privileged than the token /// specified by the InAccessToken parameter. /// /// /// If the SAFER_TOKEN_WANT_FLAGS flag is set, and the SAFER_TOKEN_COMPARE_ONLY flag is not set, this parameter is an /// LPDWORD value that specifies the flags used to create the restricted token. /// /// /// TRUE if the function succeeds; otherwise, FALSE. For extended information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safercomputetokenfromlevel BOOL // SaferComputeTokenFromLevel( SAFER_LEVEL_HANDLE LevelHandle, HANDLE InAccessToken, PHANDLE OutAccessToken, DWORD dwFlags, LPVOID // lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "39406331-3101-48f2-8b92-e049849b2b38")] // [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE LevelHandle, // HANDLE InAccessToken, ref IntPtr OutAccessToken, uint dwFlags, IntPtr lpReserved); [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE LevelHandle, HTOKEN InAccessToken, out SafeHTOKEN OutAccessToken, SAFER_TOKEN_FLAGS dwFlags, out uint lpReserved); /// The SaferCreateLevel function opens a SAFER_LEVEL_HANDLE. /// /// The scope of the level to be created. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// SAFER_SCOPEID_MACHINE 1 /// The scope of the created level is by computer. /// /// /// SAFER_SCOPEID_USER 2 /// The scope of the created level is by user. /// /// /// /// /// The level of the handle to be opened. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// SAFER_LEVELID_CONSTRAINED 0x10000 /// /// Software cannot access certain resources, such as cryptographic keys and credentials, regardless of the user rights of the user. /// /// /// /// SAFER_LEVELID_DISALLOWED 0x00000 /// Software will not run, regardless of the user rights of the user. /// /// /// SAFER_LEVELID_FULLYTRUSTED 0x40000 /// Software user rights are determined by the user rights of the user. /// /// /// SAFER_LEVELID_NORMALUSER 0x20000 /// /// Allows programs to execute as a user that does not have Administrator or Power User user rights. Software can access resources /// accessible by normal users. /// /// /// /// SAFER_LEVELID_UNTRUSTED 0x01000 /// /// Allows programs to execute with access only to resources granted to open well-known groups, blocking access to Administrator and /// Power User privileges and personally granted rights. /// /// /// /// /// /// This can be the following value. /// /// /// Value /// Meaning /// /// /// SAFER_LEVEL_OPEN 1 /// /// /// /// /// /// The returned SAFER_LEVEL_HANDLE. When you have finished using the handle, close it by calling the SaferCloseLevel function. /// /// This parameter is reserved for future use. Set it to NULL. /// /// Returns nonzero if successful or zero otherwise. /// For extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safercreatelevel BOOL SaferCreateLevel( DWORD dwScopeId, // DWORD dwLevelId, DWORD OpenFlags, SAFER_LEVEL_HANDLE *pLevelHandle, LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "7deb1365-5355-4983-900b-8e4fed009403")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferCreateLevel(SAFER_SCOPEID dwScopeId, SAFER_LEVELID dwLevelId, SAFER_LEVEL_CREATE_FLAGS OpenFlags, out SafeSAFER_LEVEL_HANDLE pLevelHandle, IntPtr lpReserved = default); /// The SaferGetLevelInformation function retrieves information about a policy level. /// The handle of the level to be queried. /// /// /// A SAFER_OBJECT_INFO_CLASS enumeration value that specifies the type of object information that should be returned. The specified /// value determines the size and type of the lpQueryBuffer parameter. The following table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// SaferObjectLevelId 1 /// Queries for the LEVELID constant. lpQueryBuffer return type: DWORD. /// /// /// SaferObjectScopeId 2 /// Queries for the user or machine scope. lpQueryBuffer return type: DWORD. /// /// /// SaferObjectFriendlyName 3 /// Queries for the display name. lpQueryBuffer return type: LPCWSTR. /// /// /// SaferObjectDescription 4 /// Queries for the description. lpQueryBuffer return type: LPCWSTR. /// /// /// /// /// A buffer to contain the results of the query. For the type of the returned information for each possible value of the dwInfoType /// parameter, see the dwInfoType parameter. /// /// The size of the lpQueryBuffer parameter in bytes. /// A pointer to return the output size of the lpQueryBuffer parameter. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safergetlevelinformation BOOL SaferGetLevelInformation( // SAFER_LEVEL_HANDLE LevelHandle, SAFER_OBJECT_INFO_CLASS dwInfoType, LPVOID lpQueryBuffer, DWORD dwInBufferSize, LPDWORD // lpdwOutBufferSize ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "cbe73ebc-bf2c-4d39-a203-78ff1a407481")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferGetLevelInformation(SAFER_LEVEL_HANDLE LevelHandle, SAFER_OBJECT_INFO_CLASS dwInfoType, IntPtr lpQueryBuffer, uint dwInBufferSize, out uint lpdwOutBufferSize); /// /// The SaferGetPolicyInformation function gets information about a policy. You can query to find out more information about /// the policy. /// /// /// The scope of the query. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// SAFER_SCOPEID_MACHINE 1 /// The scope of the query is by computer. /// /// /// SAFER_SCOPEID_USER 2 /// The scope of the query is by user. /// /// /// /// /// /// A SAFER_POLICY_INFO_CLASS enumeration value that specifies the type of policy information that should be returned. The specified /// value determines the size and type of the InfoBuffer parameter. The following table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// SaferPolicyLevelList 1 /// Queries for the list of all levels defined in a policy. InfoBuffer return type: DWORD array of LevelIds. /// /// /// SaferPolicyEnableTransparentEnforcement 2 /// Queries for the policy value to determine whether DLL checking is enabled. InfoBuffer return type: DWORD Boolean. /// /// /// SaferPolicyDefaultLevel 3 /// Queries for the default policy level. InfoBuffer return type: DWORD LevelId. /// /// /// SaferPolicyEvaluateUserScope 4 /// Queries to determine whether user scope rules should be consulted during policy evaluation. InfoBuffer return type: DWORD. /// /// /// SaferPolicyScopeFlags 5 /// /// Queries to determine whether the policy is to skip members of the local administrators group. InfoBuffer return type: DWORD. /// /// /// /// /// The size, in bytes, of the InfoBuffer parameter. /// /// A buffer to contain the results of the query. The size and type of the returned information is determined by the /// SaferPolicyInfoClass parameter. For the type of the returned information for each possible value of the SaferPolicyInfoClass /// parameter, see the SaferPolicyInfoClass parameter. /// /// The number of bytes in the InfoBuffer parameter that were filled with policy information. /// Reserved for future use. This parameter should be set to NULL. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safergetpolicyinformation BOOL // SaferGetPolicyInformation( DWORD dwScopeId, SAFER_POLICY_INFO_CLASS SaferPolicyInfoClass, DWORD InfoBufferSize, PVOID InfoBuffer, // PDWORD InfoBufferRetSize, LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "1c69d3c1-87e6-42cd-9acb-4c3d06801401")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferGetPolicyInformation(SAFER_SCOPEID dwScopeId, SAFER_POLICY_INFO_CLASS SaferPolicyInfoClass, uint InfoBufferSize, IntPtr InfoBuffer, out uint InfoBufferRetSize, IntPtr lpReserved = default); /// The SaferIdentifyLevel function retrieves information about a level. /// Number of SAFER_CODE_PROPERTIES structures in the pCodeproperties parameter. /// /// Array of SAFER_CODE_PROPERTIES structures. Each structure contains a code file to be checked and the criteria used to check the file. /// /// /// The returned SAFER_LEVEL_HANDLE. When you have finished using the handle, close it by calling the SaferCloseLevel function. /// /// /// Reserved for future use. Should be set to NULL. /// Beginning with Windows 8 and Windows Server 2012 SRP_POLICY_APPX is defined as Windows Store app. /// /// TRUE if a SAFER_LEVEL_HANDLE was opened; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-saferidentifylevel BOOL SaferIdentifyLevel( DWORD // dwNumProperties, PSAFER_CODE_PROPERTIES pCodeProperties, SAFER_LEVEL_HANDLE *pLevelHandle, LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "f82c4f40-5c37-4f97-95a2-4b2cc26bf41e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferIdentifyLevel(uint dwNumProperties, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] SAFER_CODE_PROPERTIES_V1[] pCodeProperties, out SafeSAFER_LEVEL_HANDLE pLevelHandle, [Optional, MarshalAs(UnmanagedType.LPWStr)] string lpReserved); /// The SaferIdentifyLevel function retrieves information about a level. /// Number of SAFER_CODE_PROPERTIES structures in the pCodeproperties parameter. /// /// Array of SAFER_CODE_PROPERTIES structures. Each structure contains a code file to be checked and the criteria used to check the file. /// /// /// The returned SAFER_LEVEL_HANDLE. When you have finished using the handle, close it by calling the SaferCloseLevel function. /// /// /// Reserved for future use. Should be set to NULL. /// Beginning with Windows 8 and Windows Server 2012 SRP_POLICY_APPX is defined as Windows Store app. /// /// TRUE if a SAFER_LEVEL_HANDLE was opened; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-saferidentifylevel BOOL SaferIdentifyLevel( DWORD // dwNumProperties, PSAFER_CODE_PROPERTIES pCodeProperties, SAFER_LEVEL_HANDLE *pLevelHandle, LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "f82c4f40-5c37-4f97-95a2-4b2cc26bf41e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferIdentifyLevel(uint dwNumProperties, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] SAFER_CODE_PROPERTIES_V2[] pCodeProperties, out SafeSAFER_LEVEL_HANDLE pLevelHandle, [Optional, MarshalAs(UnmanagedType.LPWStr)] string lpReserved); /// /// The SaferiIsExecutableFileType function determines whether a specified file is an executable file. Applications use this /// function to determine whether a file is an executable file, and if it is, then the application can take security precautions to /// prevent invoking untrustworthy code. /// /// /// Pointer to a null-terminated Unicode character string for the name of the file. The path is optional because only the file /// name extension is evaluated. The evaluation of the file name extension is not case-sensitive. This parameter cannot be /// NULL or an empty string, and the specified file must include a file name extension. /// /// /// Boolean value that determines whether .exe files are treated as executable files for the file type evaluation. Set this value to /// TRUE to omit .exe files from the evaluation or to FALSE to include them. /// /// /// If the function successfully recognizes the file name's extension as an executable file type, the return value is TRUE. /// If the function fails, or if szFullPath identifies a file name with a nonexecutable extension, the function returns FALSE. /// /// /// The following file name extensions are examples of executable file types. This is not a complete list. /// /// /// .bat /// /// /// .cmd /// /// /// .com /// /// /// .exe /// /// /// .js /// /// /// .lnk /// /// /// .pif /// /// /// .pl /// /// /// .shs /// /// /// .url /// /// /// .vbs /// /// /// /// The security policy Microsoft Management Console (MMC) snap-in (Secpol.msc) controls which extensions are considered executable /// file types. /// /// To view or modify the extensions that are considered executable file types /// /// /// Run Secpol.msc. /// /// /// Expand Software Restriction Policies, and then double-click Designated File Types. /// /// /// /// Note To view the Designated File Types property page, you may need to create the Software Restriction /// Policies node. To create the Software Restriction Policies node, follow the instructions that appear when you expand /// Software Restriction Policies. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-saferiisexecutablefiletype BOOL // SaferiIsExecutableFileType( LPCWSTR szFullPathname, BOOLEAN bFromShellExecute ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "f122ceaa-65bb-4cfe-a760-adf4f910c487")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferiIsExecutableFileType([MarshalAs(UnmanagedType.LPWStr)] string szFullPathname, [MarshalAs(UnmanagedType.U1)] bool bFromShellExecute); /// /// Gets the level of a hash identification rule that matches the specified hash. /// /// This function has no associated import library and is not declared in a public header. You must define a function pointer with /// the signature of this function, and you must use the LoadLibrary and GetProcAddress functions to dynamically link /// to Advapi32.dll. /// /// We recommend using the SaferIdentifyLevel function to evaluate software restriction policies. /// /// The identifier of the algorithm used to create the hash. /// A pointer to an array of bytes that contains the hash. /// The size, in bytes, of the pHashBytes array. /// The size, in bytes, of the original image from which the hash was computed. /// A pointer to the level identifier for the matching hash identification rule. /// Reserved. Set this value to zero. /// TRUE if the function is successful; otherwise, FALSE. // https://docs.microsoft.com/en-us/windows/desktop/DevNotes/saferisearchmatchinghashrules BOOL WINAPI SaferiSearchMatchingHashRules( // _In_opt_ ALG_ID HashAlgorithm, _In_ PBYTE pHashBytes, _In_ DWORD dwHashSize, _In_opt_ DWORD dwOriginalImageSize, _Out_ PDWORD // pdwFoundLevel, PDWORD pdwSaferFlags ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("", MSDNShortId = "1592c8da-31c0-45fb-b832-d439dd53c277")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferiSearchMatchingHashRules(ALG_ID HashAlgorithm, byte[] pHashBytes, uint dwHashSize, uint dwOriginalImageSize, out SAFER_LEVELID pdwFoundLevel, IntPtr pdwSaferFlags = default); /// The SaferRecordEventLogEntry function saves messages to an event log. /// SAFER_LEVEL_HANDLE that contains the details of the rule to send to the event log. /// Path of the file that attempted to run. /// Reserved for future use. This parameter should be set to NULL. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. /// /// If SaferIdentifyLevel returns a SAFER_LEVEL_HANDLE with a LevelId that is anything other than SAFER_LEVELID_FULLYTRUSTED /// (0x40000), SaferRecordEventLogEntry can be called to facilitate troubleshooting. For example, clicking a button in /// excel.exe might attempt to launch another process that is not fully trusted. This might display an obscure error message because /// the program remapped the error returned from CreateProcess. To ease troubleshooting, some Safer functions call /// SaferRecordEventLogEntry to send an event to the event log. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-saferrecordeventlogentry BOOL SaferRecordEventLogEntry( // SAFER_LEVEL_HANDLE hLevel, LPCWSTR szTargetPath, LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "7eb48f80-3a57-46ec-aca1-6ff8c1c514c6")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferRecordEventLogEntry(SAFER_LEVEL_HANDLE hLevel, [MarshalAs(UnmanagedType.LPWStr)] string szTargetPath, IntPtr lpReserved = default); /// The SaferSetLevelInformation function sets the information about a policy level. /// The handle of the level to be set. /// /// /// A SAFER_OBJECT_INFO_CLASS enumeration value that specifies the type of object information that should be set. The specified value /// determines the size and type of the lpQueryBuffer parameter. The following table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// SaferObjectLevelId 1 /// Sets the LEVELID constant. lpQueryBuffer return type: DWORD. /// /// /// SaferObjectScopeId 2 /// Sets the user or machine scope. lpQueryBuffer return type: DWORD. /// /// /// SaferObjectFriendlyName 3 /// Sets the display name. lpQueryBuffer return type: LPCWSTR. /// /// /// SaferObjectDescription 4 /// Sets the description. lpQueryBuffer return type: LPCWSTR. /// /// /// /// /// A buffer to contain the results of the query. For the type of the returned information for each possible value of the dwInfoType /// parameter, see the dwInfoType parameter. /// /// The size, in bytes, of the lpQueryBuffer parameter. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safersetlevelinformation BOOL SaferSetLevelInformation( // SAFER_LEVEL_HANDLE LevelHandle, SAFER_OBJECT_INFO_CLASS dwInfoType, LPVOID lpQueryBuffer, DWORD dwInBufferSize ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "8DB13F94-1736-4C05-B072-BFBFC076A726")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferSetLevelInformation(SAFER_LEVEL_HANDLE LevelHandle, SAFER_OBJECT_INFO_CLASS dwInfoType, IntPtr lpQueryBuffer, uint dwInBufferSize); /// The SaferSetPolicyInformation function sets the global policy controls. /// /// The scope of the query. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// SAFER_SCOPEID_MACHINE 1 /// The scope of the query is by computer. /// /// /// SAFER_SCOPEID_USER 2 /// The scope of the query is by user. /// /// /// /// /// /// A SAFER_POLICY_INFO_CLASS enumeration value that specifies the type of policy information that should be set. The specified value /// determines the size and type of the InfoBuffer parameter. The following table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// SaferPolicyLevelList 1 /// Sets the list of all levels defined in a policy. InfoBuffer return type: DWORD array of LevelIds. /// /// /// SaferPolicyEnableTransparentEnforcement 2 /// Sets the policy value to determine whether DLL checking is enabled. InfoBuffer return type: DWORD Boolean. /// /// /// SaferPolicyDefaultLevel 3 /// Sets the default policy level. InfoBuffer return type: DWORD LevelId. /// /// /// SaferPolicyEvaluateUserScope 4 /// Sets whether user scope rules should be consulted during policy evaluation. InfoBuffer return type: DWORD. /// /// /// SaferPolicyScopeFlags 5 /// Sets whether the policy is to skip members of the local administrators group. InfoBuffer return type: DWORD. /// /// /// /// The size, in bytes, of the InfoBuffer parameter. /// /// A buffer to contain the results of the query. The size and type of the returned information is determined by the /// SaferPolicyInfoClass parameter. For the type of the returned information for each possible value of the SaferPolicyInfoClass /// parameter, see the SaferPolicyInfoClass parameter. /// /// Reserved for future use. This parameter should be set to NULL. /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastError. // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/nf-winsafer-safersetpolicyinformation BOOL // SaferSetPolicyInformation( DWORD dwScopeId, SAFER_POLICY_INFO_CLASS SaferPolicyInfoClass, DWORD InfoBufferSize, PVOID InfoBuffer, // LPVOID lpReserved ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winsafer.h", MSDNShortId = "B8F3AFC4-8CAD-4AD2-AF17-CCE05A315AD8")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SaferSetPolicyInformation(SAFER_SCOPEID dwScopeId, SAFER_POLICY_INFO_CLASS SaferPolicyInfoClass, uint InfoBufferSize, IntPtr InfoBuffer, IntPtr lpReserved = default); /// /// /// The SAFER_CODE_PROPERTIES_V1 structure contains code image information and criteria to be checked on the code image. An /// array of SAFER_CODE_PROPERTIES_V1 structures is passed to the SaferIdentifyLevel function. /// /// /// SAFER_CODE_PROPERTIES_V1 does not include the new members for Windows Store app packages. Existing binary callers can distinguish /// which version by checking the cbSize member. /// /// /// /// SAFER_CODE_PROPERTIES was redefined to include additional members that allow Windows Store app to use the structure. Check the /// cbSize member for the appropriate size of the structure and for whether you should use the SAFER_CODE_PROPERTIES /// structure or the SAFER_CODE_PROPERTIES_V1 structure. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/ns-winsafer-safer_code_properties_v1 typedef struct // _SAFER_CODE_PROPERTIES_V1 { DWORD cbSize; DWORD dwCheckFlags; LPCWSTR ImagePath; HANDLE hImageFileHandle; DWORD UrlZoneId; BYTE // ImageHash[SAFER_MAX_HASH_SIZE]; DWORD dwImageHashSize; LARGE_INTEGER ImageSize; ALG_ID HashAlgorithm; LPBYTE pByteBlock; HWND // hWndParent; DWORD dwWVTUIChoice; } SAFER_CODE_PROPERTIES_V1, *PSAFER_CODE_PROPERTIES_V1; [PInvokeData("winsafer.h", MSDNShortId = "E09D287B-7223-4CAF-B404-61FB6871B622")] [StructLayout(LayoutKind.Sequential)] public struct SAFER_CODE_PROPERTIES_V1 { /// The size, in bytes, of this structure. This is used for future and backward compatibility. public uint cbSize; /// /// /// The types of criteria considered when evaluating this structure. Some flags might be silently ignored if some or all of their /// associated structure elements are not supplied. Specifying zero for this parameter causes the entire structure's contents to /// be ignored. /// /// The following table shows the possible values. These values can be combined by using a bitwise- OR operation. /// /// /// Value /// Meaning /// /// /// SAFER_CRITERIA_IMAGEPATH 0x00001 /// Check the code image path. /// /// /// SAFER_CRITERIA_IMAGEHASH 0x00004 /// Check the code hash. /// /// /// SAFER_CRITERIA_AUTHENTICODE 0x00008 /// /// Check the Authenticode signature. If this value is used, either the hImageFileHandle member or the ImagePath member must be set. /// /// /// /// SAFER_CRITERIA_URLZONE 0x00010 /// Check the URL of origin. /// /// /// SAFER_CRITERIA_IMAGEPATH_NT 0x01000 /// Check the Windows NT image path. /// /// /// public SAFER_CRITERIA dwCheckFlags; /// /// A string that specifies the fully qualified path and file name to be used for discrimination checks based on the path. The /// image path is also used to open and read the file to identify any other discrimination criteria not supplied in this /// structure. This member can be NULL; however, if the dwCheckFlags member includes /// SAFER_CRITERIA_AUTHENTICODE, either this member or the hImageFileHandle member must be set. /// [MarshalAs(UnmanagedType.LPWStr)] public string ImagePath; /// /// A file handle to a code image with at least GENERIC_READ access. The handle is used instead of explicitly reopening the file /// to compute discrimination criteria not supplied in this structure. This member can be NULL; however, if /// dwCheckFlags includes SAFER_CRITERIA_AUTHENTICODE, either this member or the ImagePath member must be set. /// public HFILE hImageFileHandle; /// /// The predetermined Internet Explorer security zones. The following zones are defined: /// /// /// URLZONE_LOCAL_MACHINE /// /// /// URLZONE_INTRANET /// /// /// URLZONE_TRUSTED /// /// /// URLZONE_INTERNET /// /// /// URLZONE_UNTRUSTED /// /// /// This member can be set to 0. /// public URLZONE UrlZoneId; /// /// /// The precomputed hash of the image. The supplied hash is interpreted as valid if both the ImageSize member and the /// dwImageHashSize member are nonzero and the HashAlgorithm member contains a valid hashing algorithm from Wincrypt.h. /// /// If the supplied hash fails to meet these conditions, the hash is automatically recomputed by: /// /// /// Using the ImageSize member and the pByteBlock member, if both are nonzero. /// /// /// Using the hImageFileHandle member, if it is not NULL. /// /// /// Opening and using the ImagePath member, if it is not NULL. /// /// /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = SAFER_MAX_HASH_SIZE)] public byte[] ImageHash; /// The size, in bytes, of the ImageHash member. public uint dwImageHashSize; /// /// The size, in bytes, of the pByteBlock member. This member is not used if the pByteBlock member is NULL. /// public long ImageSize; /// The hash algorithm used to create the ImageHash member. public ALG_ID HashAlgorithm; /// /// The memory block that contains the image of the code being checked. This member is optional. If this member is specified, the /// ImageSize member must also be supplied. /// public IntPtr pByteBlock; /// /// The arguments used for Authenticode signer certificate verification. These arguments are passed to the WinVerifyTrust /// function and control the UI that prompts the user to accept or reject entrusted certificates. /// public HWND hWndParent; /// /// Indicates the type of UI used. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// WTD_UI_ALL /// Display all UI. /// /// /// WTD_UI_NONE /// Display no UI. /// /// /// WTD_UI_NOBAD /// Display UI only if there were no errors. /// /// /// WTD_UI_NOGOOD /// Display UI only if an error occurs. /// /// /// // TODO: Replace with WTD_UI once WinTrust.dll is supported public uint dwWVTUIChoice; } /// /// /// The SAFER_CODE_PROPERTIES structure contains code image information and criteria to be checked on the code image. An array /// of SAFER_CODE_PROPERTIES structures is passed to the SaferIdentifyLevel function. /// /// /// SAFER_CODE_PROPERTIES_V2 is a redefinition of SAFER_CODE_PROPERTIES and is an extended version of SAFER_CODE_PROPERTIES_V1 /// because it includes new members for Windows Store app packages. Existing binary callers can distinguish which version by checking /// the cbSize member. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winsafer/ns-winsafer-safer_code_properties_v2 typedef struct // _SAFER_CODE_PROPERTIES_V2 { DWORD cbSize; DWORD dwCheckFlags; LPCWSTR ImagePath; HANDLE hImageFileHandle; DWORD UrlZoneId; BYTE // ImageHash[SAFER_MAX_HASH_SIZE]; DWORD dwImageHashSize; LARGE_INTEGER ImageSize; ALG_ID HashAlgorithm; LPBYTE pByteBlock; HWND // hWndParent; DWORD dwWVTUIChoice; LPCWSTR PackageMoniker; LPCWSTR PackagePublisher; LPCWSTR PackageName; ULONG64 PackageVersion; // BOOL PackageIsFramework; } SAFER_CODE_PROPERTIES_V2, *PSAFER_CODE_PROPERTIES_V2; [PInvokeData("winsafer.h", MSDNShortId = "039a37a9-1744-4cff-919e-e0da50d7b291")] [StructLayout(LayoutKind.Sequential)] public struct SAFER_CODE_PROPERTIES_V2 { /// The size of this structure in bytes. This is used for future and backward compatibility. public uint cbSize; /// /// /// The types of criteria considered when evaluating this structure. Some flags might be silently ignored if some or all of their /// associated structure elements are not supplied. Specifying zero for this parameter causes the entire structure's contents to /// be ignored. /// /// The following table shows the possible values. These values may be combined using a bitwise- OR operation. /// /// /// Value /// Meaning /// /// /// SAFER_CRITERIA_IMAGEPATH 0x00001 /// Check the code image path. /// /// /// SAFER_CRITERIA_IMAGEHASH 0x00004 /// Check the code hash. /// /// /// SAFER_CRITERIA_AUTHENTICODE 0x00008 /// /// Check the Authenticode signature. If this value is used, either the hImageFileHandle member or the ImagePath member must be set. /// /// /// /// SAFER_CRITERIA_URLZONE 0x00010 /// Check the URL of origin. /// /// /// SAFER_CRITERIA_IMAGEPATH_NT 0x01000 /// Check the Windows NT image path. /// /// /// SAFER_CRITERIA_APPX_PACKAGE 0x00020 /// Check for a Windows Store app package. For use by Windows Store apps. /// /// /// public SAFER_CRITERIA dwCheckFlags; /// /// A string specifying the fully qualified path and file name to be used for discrimination checks based on the path. The image /// path is also used to open and read the file to identify any other discrimination criteria not supplied in this structure. /// This member can be NULL; however, if the dwCheckFlags member includes SAFER_CRITERIA_AUTHENTICODE, /// either this member or the hImageFileHandle member must be set. /// [MarshalAs(UnmanagedType.LPWStr)] public string ImagePath; /// /// A file handle to a code image with at least GENERIC_READ access. The handle is used instead of explicitly reopening the file /// to compute discrimination criteria not supplied in this structure. This member can be NULL; however, if /// dwCheckFlags includes SAFER_CRITERIA_AUTHENTICODE, either this member or the ImagePath member must be set. /// public HFILE hImageFileHandle; /// /// The predetermined Internet Explorer security zones. The following zones are defined: /// /// /// URLZONE_LOCAL_MACHINE /// /// /// URLZONE_INTRANET /// /// /// URLZONE_TRUSTED /// /// /// URLZONE_INTERNET /// /// /// URLZONE_UNTRUSTED /// /// /// This member can be set to 0. /// public URLZONE UrlZoneId; /// /// /// The pre-computed hash of the image. The supplied hash is interpreted as valid if both the ImageSize member and the /// dwImageHashSize member are nonzero and the HashAlgorithm member contains a valid hashing algorithm from Wincrypt.h. /// /// If the supplied hash fails to meet these conditions, the hash will be automatically recomputed by: /// /// /// Using the ImageSize member and the pByteBlock member if both are nonzero. /// /// /// Using the hImageFileHandle member if it is not NULL. /// /// /// Opening and using the ImagePath member if it is not NULL. /// /// /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = SAFER_MAX_HASH_SIZE)] public byte[] ImageHash; /// The size in bytes of the ImageHash member. public uint dwImageHashSize; /// /// The size in bytes of the pByteBlock member. This member is not used if the pByteBlock member is NULL. /// public long ImageSize; /// The hash algorithm used to create the ImageHash member. public ALG_ID HashAlgorithm; /// /// The memory block containing the image of the code being checked. This member is optional. If this member is specified, the /// ImageSize member must also be supplied. /// public IntPtr pByteBlock; /// /// The arguments used for Authenticode signer certificate verification. These arguments are passed to the WinVerifyTrust /// function and control the user interface (UI) that prompts the user to accept or reject entrusted certificates. /// public HWND hWndParent; /// /// Indicates the type of UI used. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// WTD_UI_ALL /// Display all UI. /// /// /// WTD_UI_NONE /// Display no UI. /// /// /// WTD_UI_NOBAD /// Display UI only if there were no errors. /// /// /// WTD_UI_NOGOOD /// Display UI only if an error occurs. /// /// /// // TODO: Replace with WTD_UI once WinTrust.dll is supported public uint dwWVTUIChoice; /// /// The package moniker property. For use by Windows Store apps. /// /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This member /// is not available. /// /// [MarshalAs(UnmanagedType.LPWStr)] public string PackageMoniker; /// /// The package publisher property. For use by Windows Store apps. /// /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This member /// is not available. /// /// [MarshalAs(UnmanagedType.LPWStr)] public string PackagePublisher; /// /// The package name property. For use by Windows Store apps. /// /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This member /// is not available. /// /// [MarshalAs(UnmanagedType.LPWStr)] public string PackageName; /// /// The package version property. For use by Windows Store apps. /// /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This member /// is not available. /// /// public ulong PackageVersion; /// /// The package is a framework package. For use by Windows Store apps. /// /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This member /// is not available. /// /// [MarshalAs(UnmanagedType.Bool)] public bool PackageIsFramework; } /// Provides a handle to a safer level. [StructLayout(LayoutKind.Sequential)] public struct SAFER_LEVEL_HANDLE : IHandle { private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public SAFER_LEVEL_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static SAFER_LEVEL_HANDLE NULL => new SAFER_LEVEL_HANDLE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(SAFER_LEVEL_HANDLE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator SAFER_LEVEL_HANDLE(IntPtr h) => new SAFER_LEVEL_HANDLE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(SAFER_LEVEL_HANDLE h1, SAFER_LEVEL_HANDLE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(SAFER_LEVEL_HANDLE h1, SAFER_LEVEL_HANDLE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is SAFER_LEVEL_HANDLE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeSAFER_LEVEL_HANDLE : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeSAFER_LEVEL_HANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeSAFER_LEVEL_HANDLE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator SAFER_LEVEL_HANDLE(SafeSAFER_LEVEL_HANDLE h) => h.handle; /// protected override bool InternalReleaseHandle() => SaferCloseLevel(handle); } } }