using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke { public static partial class AdvApi32 { /// /// Flags that specify the conditions under which the security event type specified by the AuditSubCategoryGuid and AuditCategoryGuid members are audited. /// [PInvokeData("ntsecapi.h")] [Flags] public enum AuditCondition : uint { /// Do not change auditing options for the specified event type. /// This value is valid for the AuditSetSystemPolicy and AuditQuerySystemPolicy functions. POLICY_AUDIT_EVENT_UNCHANGED = 0x00000000, /// Audit successful occurrences of the specified event type. /// This value is valid for the AuditSetSystemPolicy and AuditQuerySystemPolicy functions. POLICY_AUDIT_EVENT_SUCCESS = 0x00000001, /// Audit failed attempts to cause the specified event type. /// This value is valid for the AuditSetSystemPolicy and AuditQuerySystemPolicy functions. POLICY_AUDIT_EVENT_FAILURE = 0x00000002, /// Do not audit the specified event type. /// This value is valid for the AuditSetSystemPolicy and AuditQuerySystemPolicy functions. POLICY_AUDIT_EVENT_NONE = 0x00000004, /// Do not change auditing options for the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_POLICY_UNCHANGED = 0x00, /// Audit successful occurrences of the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_AUDIT_SUCCESS_INCLUDE = 0x01, /// Do not audit successful occurrences of the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_AUDIT_SUCCESS_EXCLUDE = 0x02, /// Audit failed attempts to cause the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_AUDIT_FAILURE_INCLUDE = 0x04, /// Do not audit failed attempts to cause the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_AUDIT_FAILURE_EXCLUDE = 0x08, /// Do not audit the specified event type. /// This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. PER_USER_AUDIT_NONE = 0x10, } /// /// The POLICY_AUDIT_EVENT_TYPE enumeration defines values that indicate the types of events the system can audit. The /// LsaQueryInformationPolicy and LsaSetInformationPolicy functions use this enumeration when their InformationClass parameters are /// set to PolicyAuditEventsInformation. /// /// /// The POLICY_AUDIT_EVENT_TYPE enumeration may expand in future versions of Windows. Because of this, you should not compute /// the number of values in this enumeration directly. Instead, you should obtain the count of values by calling /// LsaQueryInformationPolicy with the InformationClass parameter set to PolicyAuditEventsInformation and extract the count from the /// MaximumAuditEventCount member of the returned POLICY_AUDIT_EVENTS_INFO structure. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ne-ntsecapi-_policy_audit_event_type typedef enum // _POLICY_AUDIT_EVENT_TYPE { AuditCategorySystem, AuditCategoryLogon, AuditCategoryObjectAccess, AuditCategoryPrivilegeUse, // AuditCategoryDetailedTracking, AuditCategoryPolicyChange, AuditCategoryAccountManagement, AuditCategoryDirectoryServiceAccess, // AuditCategoryAccountLogon } POLICY_AUDIT_EVENT_TYPE, *PPOLICY_AUDIT_EVENT_TYPE; [PInvokeData("ntsecapi.h", MSDNShortId = "e8dbd1d5-37d5-4a97-9d1c-c645871dc7a5")] public enum POLICY_AUDIT_EVENT_TYPE { /// Determines whether the operating system must audit any of the following attempts: AuditCategorySystem, /// /// Determines whether the operating system must audit each time this computer validates the credentials of an account. Account /// logon events are generated whenever a computer validates the credentials of one of its local accounts. The credential /// validation can be in support of a local logon or, in the case of an Active Directory domain account on a domain controller, /// can be in support of a logon to another computer. Audited events for local accounts must be logged on the local security log /// of the computer. Account logoff does not generate an event that can be audited. /// AuditCategoryLogon, /// /// Determines whether the operating system must audit each instance of user attempts to access a non-Active Directory object, /// such as a file, that has its own system access control list (SACL) specified. The type of access request, such as Write, /// Read, or Modify, and the account that is making the request must match the settings in the SACL. /// AuditCategoryObjectAccess, /// Determines whether the operating system must audit each instance of user attempts to use privileges. AuditCategoryPrivilegeUse, /// /// Determines whether the operating system must audit specific events, such as program activation, some forms of handle /// duplication, indirect access to an object, and process exit. /// AuditCategoryDetailedTracking, /// /// Determines whether the operating system must audit attempts to change Policy object rules, such as user rights assignment /// policy, audit policy, account policy, or trust policy. /// AuditCategoryPolicyChange, /// /// Determines whether the operating system must audit attempts to create, delete, or change user or group accounts. Also, audit /// password changes. /// AuditCategoryAccountManagement, /// /// Determines whether the operating system must audit attempts to access the directory service. The Active Directory object has /// its own SACL specified. The type of access request, such as Write, Read, or Modify, and the account that is making the /// request must match the settings in the SACL. /// AuditCategoryDirectoryServiceAccess, /// /// Determines whether the operating system must audit each instance of a user attempt to log on or log off this computer. Also /// audits logon attempts by privileged accounts that log on to the domain controller. These audit events are generated when the /// Kerberos Key Distribution Center (KDC) logs on to the domain controller. Logoff attempts are generated whenever the logon /// session of a logged-on user account is terminated. /// AuditCategoryAccountLogon, } /// /// The AuditComputeEffectivePolicyBySid function computes the effective audit policy for one or more subcategories for the /// specified security principal. The function computes effective audit policy by combining system audit policy with per-user policy. /// /// /// A pointer to the SID structure associated with the principal for which to compute effective audit policy. Per-user policy for /// group SIDs is not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to compute effective audit policy. For a /// list of defined subcategories, see Auditing Constants. /// /// The number of elements in each of the pSubCategoryGuids and ppAuditPolicy arrays. /// /// /// A pointer to a single buffer that contains both an array of pointers to AUDIT_POLICY_INFORMATION structures and the structures /// themselves. The AUDIT_POLICY_INFORMATION structures specify the effective audit policy for the subcategories specified by /// the pSubCategoryGuids array. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 (0x57) /// One or more parameters are not valid. /// /// /// ERROR_FILE_NOT_FOUND 2 (0x2) /// No per-user audit policy exists for the principal specified by the pSid parameter. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_QUERY_SYSTEM_POLICY and /// AUDIT_QUERY_USER_POLICY access on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditcomputeeffectivepolicybysid BOOLEAN // AuditComputeEffectivePolicyBySid( const PSID pSid, const GUID *pSubCategoryGuids, ULONG dwPolicyCount, PAUDIT_POLICY_INFORMATION // *ppAuditPolicy ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "cac928e5-8d8f-4b2f-9c1b-c00dc891e3d1")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditComputeEffectivePolicyBySid(PSID pSid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Guid[] pSubCategoryGuids, uint dwPolicyCount, out SafeAuditMemoryHandle ppAuditPolicy); /// /// The AuditComputeEffectivePolicyBySid function computes the effective audit policy for one or more subcategories for the /// specified security principal. The function computes effective audit policy by combining system audit policy with per-user policy. /// /// /// A pointer to the SID structure associated with the principal for which to compute effective audit policy. Per-user policy for /// group SIDs is not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to compute effective audit policy. For a /// list of defined subcategories, see Auditing Constants. /// /// /// A list of AUDIT_POLICY_INFORMATION structures that specify the effective audit policy for the subcategories specified by the /// pSubCategoryGuids array. /// [PInvokeData("ntsecapi.h", MSDNShortId = "cac928e5-8d8f-4b2f-9c1b-c00dc891e3d1")] public static IEnumerable AuditComputeEffectivePolicyBySid(PSID pSid, [In] Guid[] pSubCategoryGuids) => AuditComputeEffectivePolicyBySid(pSid, pSubCategoryGuids, (uint)pSubCategoryGuids.Length, out var h) ? h.ToIEnum(pSubCategoryGuids.Length) : throw Win32Error.GetLastError().GetException(); /// /// The AuditComputeEffectivePolicyByToken function computes the effective audit policy for one or more subcategories for the /// security principal associated with the specified token. The function computes effective audit policy by combining system audit /// policy with per-user policy. /// /// /// A handle to the access token associated with the principal for which to compute effective audit policy. The token must have been /// opened with TOKEN_QUERY access. Per-user policy for group SIDs is not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to compute effective audit policy. For a /// list of defined subcategories, see Auditing Constants. /// /// The number of elements in each of the pSubCategoryGuids and ppAuditPolicy arrays. /// /// /// A pointer to a single buffer that contains both an array of pointers to AUDIT_POLICY_INFORMATION structures and the structures /// themselves. The AUDIT_POLICY_INFORMATION structures specify the effective audit policy for the subcategories specified by /// the pSubCategoryGuids array. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// ERROR_FILE_NOT_FOUND 2 (0x2) /// No per-user audit policy exists for the principal specified by the pSid parameter. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have both AUDIT_QUERY_SYSTEM_POLICY /// and AUDIT_QUERY_USER_POLICY access on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditcomputeeffectivepolicybytoken BOOLEAN // AuditComputeEffectivePolicyByToken( HANDLE hTokenHandle, const GUID *pSubCategoryGuids, ULONG dwPolicyCount, // PAUDIT_POLICY_INFORMATION *ppAuditPolicy ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "e5fc9b8d-a61e-48c2-9093-f27167232cc8")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditComputeEffectivePolicyByToken(HTOKEN hTokenHandle, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Guid[] pSubCategoryGuids, uint dwPolicyCount, out SafeAuditMemoryHandle ppAuditPolicy); /// /// The AuditComputeEffectivePolicyByToken function computes the effective audit policy for one or more subcategories for the /// security principal associated with the specified token. The function computes effective audit policy by combining system audit /// policy with per-user policy. /// /// /// A handle to the access token associated with the principal for which to compute effective audit policy. The token must have been /// opened with TOKEN_QUERY access. Per-user policy for group SIDs is not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to compute effective audit policy. For a /// list of defined subcategories, see Auditing Constants. /// /// /// A list of AUDIT_POLICY_INFORMATION structures that specify the effective audit policy for the subcategories specified by /// the pSubCategoryGuids array. /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have both AUDIT_QUERY_SYSTEM_POLICY /// and AUDIT_QUERY_USER_POLICY access on the Audit security object. /// [PInvokeData("ntsecapi.h", MSDNShortId = "e5fc9b8d-a61e-48c2-9093-f27167232cc8")] public static IEnumerable AuditComputeEffectivePolicyByToken(HTOKEN hTokenHandle, [In] Guid[] pSubCategoryGuids) => AuditComputeEffectivePolicyByToken(hTokenHandle, pSubCategoryGuids, (uint)pSubCategoryGuids.Length, out var h) ? h.ToIEnum(pSubCategoryGuids.Length) : throw Win32Error.GetLastError().GetException(); /// The AuditEnumerateCategories function enumerates the available audit-policy categories. /// /// /// A pointer to a single buffer that contains both an array of pointers to GUID structures and the structures themselves. The /// GUID structures specify the audit-policy categories available on the computer. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// A pointer to the number of elements in the ppAuditCategoriesArray array. /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditenumeratecategories BOOLEAN // AuditEnumerateCategories( GUID **ppAuditCategoriesArray, PULONG pdwCountReturned ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "bcfdb24b-182e-4845-95c0-a210915435ae")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditEnumerateCategories(out SafeAuditMemoryHandle ppAuditCategoriesArray, out uint pdwCountReturned); /// The AuditEnumerateCategories function enumerates the available audit-policy categories. /// The GUID structures that specify the audit-policy categories available on the computer. [PInvokeData("ntsecapi.h", MSDNShortId = "bcfdb24b-182e-4845-95c0-a210915435ae")] public static IEnumerable AuditEnumerateCategories() => AuditEnumerateCategories(out var h, out var i) ? h.ToIEnum((int)i) : throw Win32Error.GetLastError().GetException(); /// The AuditEnumeratePerUserPolicy function enumerates users for whom per-user auditing policy is specified. /// /// /// A pointer to a single buffer that contains both an array of pointers to POLICY_AUDIT_SID_ARRAY structures and the structures /// themselves. The POLICY_AUDIT_SID_ARRAY structures specify the users for whom per-user audit policy is specified. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_ENUMERATE_USERS access /// on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditenumerateperuserpolicy BOOLEAN // AuditEnumeratePerUserPolicy( PPOLICY_AUDIT_SID_ARRAY *ppAuditSidArray ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "4b13f021-ba08-4eb8-9c7a-0512992ef272")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditEnumeratePerUserPolicy(out SafeAuditMemoryHandle ppAuditSidArray); /// The AuditEnumeratePerUserPolicy function enumerates users for whom per-user auditing policy is specified. /// The user SIDs for whom per-user audit policy is specified. [PInvokeData("ntsecapi.h", MSDNShortId = "4b13f021-ba08-4eb8-9c7a-0512992ef272")] public static IEnumerable AuditEnumeratePerUserPolicy() => AuditEnumeratePerUserPolicy(out var h) ? h.ToStructure().UserSidArray : throw Win32Error.GetLastError().GetException(); /// The AuditEnumerateSubCategories function enumerates the available audit-policy subcategories. /// /// The GUID of an audit-policy category for which subcategories are enumerated. If the value of the bRetrieveAllSubCategories /// parameter is TRUE, this parameter is ignored. /// /// /// TRUE to enumerate all audit-policy subcategories; FALSE to enumerate only the subcategories of the audit-policy /// category specified by the pAuditCategoryGuid parameter. /// /// /// /// A pointer to a single buffer that contains both an array of pointers to GUID structures and the structures themselves. The /// GUID structures specify the audit-policy subcategories available on the computer. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// A pointer to the number of audit-policy subcategories returned in the ppAuditSubCategoriesArray array. /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditenumeratesubcategories BOOLEAN // AuditEnumerateSubCategories( const GUID *pAuditCategoryGuid, BOOLEAN bRetrieveAllSubCategories, GUID **ppAuditSubCategoriesArray, // PULONG pdwCountReturned ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "c5af83f4-9524-4a39-ad1d-39b21bb073bd")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditEnumerateSubCategories(in Guid pAuditCategoryGuid, [MarshalAs(UnmanagedType.U1)] bool bRetrieveAllSubCategories, out SafeAuditMemoryHandle ppAuditSubCategoriesArray, out uint pdwCountReturned); /// The AuditEnumerateSubCategories function enumerates the available audit-policy subcategories. /// /// The GUID of an audit-policy category for which subcategories are enumerated. If the value is , then /// all subcategories are enumerated. /// /// A list of GUID structures specify the audit-policy subcategories available on the computer. [PInvokeData("ntsecapi.h", MSDNShortId = "c5af83f4-9524-4a39-ad1d-39b21bb073bd")] public static IEnumerable AuditEnumerateSubCategories(Guid? pAuditCategoryGuid = null) { var guid = pAuditCategoryGuid.HasValue ? pAuditCategoryGuid.Value : Guid.Empty; return AuditEnumerateSubCategories(guid, !pAuditCategoryGuid.HasValue, out var h, out var c) ? h.ToIEnum((int)c) : throw Win32Error.GetLastError().GetException(); } /// The AuditFree function frees the memory allocated by audit functions for the specified buffer. /// A pointer to the buffer to free. /// This function does not return a value. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditfree void AuditFree( PVOID Buffer ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "697baf9b-91c4-4a88-a190-e9f6812e08af")] public static extern void AuditFree(IntPtr Buffer); /// /// The AuditLookupCategoryGuidFromCategoryId function retrieves a GUID structure that represents the specified /// audit-policy category. /// /// An element of the POLICY_AUDIT_EVENT_TYPE enumeration that specifies an audit-policy category. /// /// A pointer to a GUID structure that represents the audit-policy category specified by the AuditCategoryId /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditlookupcategoryguidfromcategoryid BOOLEAN // AuditLookupCategoryGuidFromCategoryId( POLICY_AUDIT_EVENT_TYPE AuditCategoryId, GUID *pAuditCategoryGuid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "2f00fe52-2e94-473a-be13-252b50b58522")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditLookupCategoryGuidFromCategoryId(POLICY_AUDIT_EVENT_TYPE AuditCategoryId, out Guid pAuditCategoryGuid); /// /// The AuditLookupCategoryIdFromCategoryGuid function retrieves an element of the POLICY_AUDIT_EVENT_TYPE enumeration that /// represents the specified audit-policy category. /// /// A pointer to a GUID structure that specifies an audit-policy category. /// /// A pointer to an element of the POLICY_AUDIT_EVENT_TYPE enumeration that represents the audit-policy category specified by the /// pAuditCategoryGuid parameter. /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditlookupcategoryidfromcategoryguid BOOLEAN // AuditLookupCategoryIdFromCategoryGuid( const GUID *pAuditCategoryGuid, PPOLICY_AUDIT_EVENT_TYPE pAuditCategoryId ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "c50e39f0-d45f-4deb-abe5-6261775b507c")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditLookupCategoryIdFromCategoryGuid(in Guid pAuditCategoryGuid, out POLICY_AUDIT_EVENT_TYPE pAuditCategoryId); /// The AuditLookupCategoryName function retrieves the display name of the specified audit-policy category. /// A pointer to a GUID structure that specifies an audit-policy category. /// /// /// The address of a pointer to a null-terminated string that contains the display name of the audit-policy category specified by the /// pAuditCategoryGuid function. /// /// When you have finished using this string, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditlookupcategorynamea BOOLEAN // AuditLookupCategoryNameA( const GUID *pAuditCategoryGuid, PSTR *ppszCategoryName ); [DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("ntsecapi.h", MSDNShortId = "8b30d864-8eb5-42d8-bc9a-a9eae1de5187")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditLookupCategoryName(in Guid pAuditCategoryGuid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(AuditStringMarshaler))] out string ppszCategoryName); /// The AuditLookupSubCategoryName function retrieves the display name of the specified audit-policy subcategory. /// A pointer to a GUID structure that specifies an audit-policy subcategory. /// /// /// The address of a pointer to a null-terminated string that contains the display name of the audit-policy subcategory specified by /// the pAuditSubCategoryGuid parameter. /// /// When you have finished using this string, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditlookupsubcategorynamea BOOLEAN // AuditLookupSubCategoryNameA( const GUID *pAuditSubCategoryGuid, PSTR *ppszSubCategoryName ); [DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("ntsecapi.h", MSDNShortId = "65ccd0f6-ee43-4b4d-98fd-b7a49f23ad9d")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditLookupSubCategoryName(in Guid pAuditSubCategoryGuid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(AuditStringMarshaler))] out string ppszSubCategoryName); /// /// The AuditQueryGlobalSacl function retrieves a global system access control list (SACL) that delegates access to the audit /// messages. Updating the global SACL requires the SeSecurityPrivilege which protects the global SACL from being updated by /// any user without administrator privileges. /// /// /// A pointer to a null-terminated string specifying the type of object being accessed. This parameter must be either "File" or /// "Key", depending on whether the object is a file or registry. This string appears in any audit message that the function generates. /// /// /// A pointer to an ACL structure that contains the SACL information. This should be freed later by calling the LocalFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditqueryglobalsacla BOOLEAN AuditQueryGlobalSaclA( // PCSTR ObjectTypeName, PACL *Acl ); [DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("ntsecapi.h", MSDNShortId = "133BBC94-9C89-437A-9146-75A9898A6566")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditQueryGlobalSacl(string ObjectTypeName, out SafePACL Acl); /// /// The AuditQueryPerUserPolicy function retrieves per-user audit policy in one or more audit-policy subcategories for the /// specified principal. /// /// /// A pointer to the SID structure associated with the principal for which to query audit policy. Per-user policy for group SIDs is /// not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to query audit policy. For a list of defined /// audit-policy subcategories, see Auditing Constants. /// /// The number of elements in each of the pSubCategoryGuids and ppAuditPolicy arrays. /// /// /// A pointer to a single buffer that contains both an array of pointers to AUDIT_POLICY_INFORMATION structures and the structures /// themselves. The AUDIT_POLICY_INFORMATION structures specify the per-user audit policy for the subcategories specified by /// the pSubCategoryGuids array. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_FILE_NOT_FOUND 2 /// No per-user audit policy exists for the principal specified by the pSid parameter. /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_QUERY_USER_POLICY access /// on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditqueryperuserpolicy BOOLEAN AuditQueryPerUserPolicy( // const PSID pSid, const GUID *pSubCategoryGuids, ULONG dwPolicyCount, PAUDIT_POLICY_INFORMATION *ppAuditPolicy ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "7d4790de-ebd6-4840-b532-7158b8d80db2")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditQueryPerUserPolicy(PSID pSid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Guid[] pSubCategoryGuids, uint dwPolicyCount, out SafeAuditMemoryHandle ppAuditPolicy); /// /// The AuditQueryPerUserPolicy function retrieves per-user audit policy in one or more audit-policy subcategories for the /// specified principal. /// /// /// A pointer to the SID structure associated with the principal for which to query audit policy. Per-user policy for group SIDs is /// not currently supported. /// /// /// A pointer to an array of GUID values that specify the subcategories for which to query audit policy. For a list of defined /// audit-policy subcategories, see Auditing Constants. /// /// /// A list of AUDIT_POLICY_INFORMATION structures that specify the per-user audit policy for the subcategories specified by /// the pSubCategoryGuids array. /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_QUERY_USER_POLICY access /// on the Audit security object. /// [PInvokeData("ntsecapi.h", MSDNShortId = "7d4790de-ebd6-4840-b532-7158b8d80db2")] public static IEnumerable AuditQueryPerUserPolicy(PSID pSid, [In] Guid[] pSubCategoryGuids) { var b = AuditQueryPerUserPolicy(pSid, pSubCategoryGuids, (uint)(pSubCategoryGuids?.Length ?? 0), out var h); if (b) return h.ToIEnum(pSubCategoryGuids?.Length ?? 0); var err = Win32Error.GetLastError(); return err == Win32Error.ERROR_FILE_NOT_FOUND ? new AUDIT_POLICY_INFORMATION[0] : throw err.GetException(); } /// The AuditQuerySecurity function retrieves security descriptor that delegates access to audit policy. /// /// A SECURITY_INFORMATION value that specifies which parts of the security descriptor this function sets. Only /// SACL_SECURITY_INFORMATION and DACL_SECURITY_INFORMATION are supported. Any other values are ignored. If neither /// SACL_SECURITY_INFORMATION nor DACL_SECURITY_INFORMATION is specified, this function fails and returns ERROR_INVALID_PARAMETER. /// /// /// The address of a pointer to a well-formed SECURITY_DESCRIPTOR structure that controls access to the Audit security object. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege. // https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-auditquerysecurity // BOOLEAN AuditQuerySecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR *ppSecurityDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "496c9659-0c03-42c9-93c4-eb4d97e950e2")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditQuerySecurity(SECURITY_INFORMATION SecurityInformation, out SafePSECURITY_DESCRIPTOR ppSecurityDescriptor); /// The AuditQuerySystemPolicy function retrieves system audit policy for one or more audit-policy subcategories. /// /// A pointer to an array of GUID values that specify the subcategories for which to query audit policy. For a list of defined /// audit-policy subcategories, see Auditing Constants. /// /// The number of elements in each of the pSubCategoryGuids and ppAuditPolicy arrays. /// /// /// A pointer to a single buffer that contains both an array of pointers to AUDIT_POLICY_INFORMATION structures and the structures /// themselves. The AUDIT_POLICY_INFORMATION structures specify the system audit policy for the subcategories specified by the /// pSubCategoryGuids array. /// /// When you have finished using this buffer, free it by calling the AuditFree function. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_FILE_NOT_FOUND 2 /// No per-user audit policy exists for the principal specified by the pSid parameter. /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_QUERY_SYSTEM_POLICY /// access on the audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditquerysystempolicy BOOLEAN AuditQuerySystemPolicy( // const GUID *pSubCategoryGuids, ULONG dwPolicyCount, PAUDIT_POLICY_INFORMATION *ppAuditPolicy ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "5c268033-65fd-4a74-90a1-4b9e1e18daf1")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditQuerySystemPolicy([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Guid[] pSubCategoryGuids, uint dwPolicyCount, out SafeAuditMemoryHandle ppAuditPolicy); /// The AuditQuerySystemPolicy function retrieves system audit policy for one or more audit-policy subcategories. /// /// A pointer to an array of GUID values that specify the subcategories for which to query audit policy. For a list of defined /// audit-policy subcategories, see Auditing Constants. /// /// /// A list of AUDIT_POLICY_INFORMATION structures that specify the system audit policy for the subcategories specified by the /// pSubCategoryGuids array. /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_QUERY_SYSTEM_POLICY /// access on the audit security object. /// [PInvokeData("ntsecapi.h", MSDNShortId = "5c268033-65fd-4a74-90a1-4b9e1e18daf1")] public static IEnumerable AuditQuerySystemPolicy([In] Guid[] pSubCategoryGuids) => AuditQuerySystemPolicy(pSubCategoryGuids, (uint)(pSubCategoryGuids?.Length ?? 0), out var h) ? h.ToIEnum(pSubCategoryGuids?.Length ?? 0) : throw Win32Error.GetLastError().GetException(); /// /// The AuditSetGlobalSacl function sets a global system access control list (SACL) that delegates access to the audit /// messages. Updating the global SACL requires the SeSecurityPrivilege which protects the global SACL from being updated by /// any user without administrator privileges. /// /// /// A pointer to a null-terminated string specifying the type of object being created or accessed. For setting the global SACL on /// files, this should be set to "File" and for setting the global SACL on registry, this should be set to "Key". This string appears /// in any audit message that the function generates. /// /// A pointer to an ACL structure. /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditsetglobalsacla BOOLEAN AuditSetGlobalSaclA( PCSTR // ObjectTypeName, PACL Acl ); [DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("ntsecapi.h", MSDNShortId = "48A41E3F-DDB0-431F-BCF0-E2452FEA57FA")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditSetGlobalSacl(string ObjectTypeName, PACL Acl); /// /// The AuditSetPerUserPolicy function sets per-user audit policy in one or more audit subcategories for the specified principal. /// /// /// A pointer to the SID structure associated with the principal for which to set audit policy. Per-user policy for group SIDs is not /// currently supported. /// /// /// /// A pointer to an array of AUDIT_POLICY_INFORMATION structures. Each structure specifies per-user audit policy for one audit subcategory. /// /// The AuditCategoryGuid member of these structures is ignored. /// /// The number of elements in the pAuditPolicy array. /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// ERROR_NO_SUCH_USER 1317 /// The SID structure specified by the pSID parameter is not associated with an existing user. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_SET_USER_POLICY access /// on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditsetperuserpolicy BOOLEAN AuditSetPerUserPolicy( // const PSID pSid, PCAUDIT_POLICY_INFORMATION pAuditPolicy, ULONG dwPolicyCount ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "a6cef640-5658-4c13-96fb-a664d2a61b57")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditSetPerUserPolicy(PSID pSid, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] AUDIT_POLICY_INFORMATION[] pAuditPolicy, uint dwPolicyCount); /// The AuditSetSecurity function sets a security descriptor that delegates access to audit policy. /// /// A SECURITY_INFORMATION value that specifies which parts of the security descriptor this function sets. Only /// SACL_SECURITY_INFORMATION and DACL_SECURITY_INFORMATION are supported. Any other values are ignored. If neither /// SACL_SECURITY_INFORMATION nor DACL_SECURITY_INFORMATION is specified, this function fails and returns ERROR_INVALID_PARAMETER. /// /// /// A pointer to a well-formed SECURITY_DESCRIPTOR structure that controls access to the Audit security object. If this parameter is /// NULL, the function fails and returns ERROR_INVALID_PARAMETER. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditsetsecurity BOOLEAN AuditSetSecurity( // SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "2f4d6198-775a-40e4-9158-a69e71bfe050")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditSetSecurity(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor); /// The AuditSetSystemPolicy function sets system audit policy for one or more audit-policy subcategories. /// /// /// A pointer to an array of AUDIT_POLICY_INFORMATION structures. Each structure specifies system audit policy for one audit-policy subcategory. /// /// The AuditCategoryGuid member of these structures is ignored. /// /// The number of elements in the pAuditPolicy array. /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. GetLastError may /// return one of the following error codes defined in WinError.h. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ACCESS_DENIED 5 /// The caller does not have the privilege or access rights necessary to call this function. /// /// /// ERROR_INVALID_PARAMETER 87 /// One or more parameters are invalid. /// /// /// /// /// To successfully call this function, the caller must have SeSecurityPrivilege or have AUDIT_SET_SYSTEM_POLICY access /// on the Audit security object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-auditsetsystempolicy BOOLEAN AuditSetSystemPolicy( // PCAUDIT_POLICY_INFORMATION pAuditPolicy, ULONG dwPolicyCount ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("ntsecapi.h", MSDNShortId = "9692ebe3-a676-45bb-a58d-b3fdbb1bbc2a")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool AuditSetSystemPolicy([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] AUDIT_POLICY_INFORMATION[] pAuditPolicy, uint dwPolicyCount); /// The AUDIT_POLICY_INFORMATION structure specifies a security event type and when to audit that type. // https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_audit_policy_information typedef struct // _AUDIT_POLICY_INFORMATION { GUID AuditSubCategoryGuid; ULONG AuditingInformation; GUID AuditCategoryGuid; } // AUDIT_POLICY_INFORMATION, *PAUDIT_POLICY_INFORMATION; [PInvokeData("ntsecapi.h", MSDNShortId = "3fafeec9-a028-4a65-933e-fb973eb257b0")] [StructLayout(LayoutKind.Sequential)] public struct AUDIT_POLICY_INFORMATION { /// A GUID structure that specifies an audit subcategory. public Guid AuditSubCategoryGuid; /// /// /// A set of bit flags that specify the conditions under which the security event type specified by the /// AuditSubCategoryGuid and AuditCategoryGuid members are audited. The following values are defined. /// /// Important Note that the meaning of these values differs depending on which function is using this structure. /// /// /// Value /// Meaning /// /// /// POLICY_AUDIT_EVENT_UNCHANGED 0x00000000 /// /// Do not change auditing options for the specified event type. This value is valid for the AuditSetSystemPolicy and /// AuditQuerySystemPolicy functions. /// /// /// /// POLICY_AUDIT_EVENT_SUCCESS 0x00000001 /// /// Audit successful occurrences of the specified event type. This value is valid for the AuditSetSystemPolicy and /// AuditQuerySystemPolicy functions. /// /// /// /// POLICY_AUDIT_EVENT_FAILURE 0x00000002 /// /// Audit failed attempts to cause the specified event type. This value is valid for the AuditSetSystemPolicy and /// AuditQuerySystemPolicy functions. /// /// /// /// POLICY_AUDIT_EVENT_NONE 0x00000004 /// /// Do not audit the specified event type. This value is valid for the AuditSetSystemPolicy and AuditQuerySystemPolicy functions. /// /// /// /// PER_USER_POLICY_UNCHANGED 0x00 /// /// Do not change auditing options for the specified event type. This value is valid for the AuditSetPerUserPolicy and /// AuditQueryPerUserPolicy functions. /// /// /// /// PER_USER_AUDIT_SUCCESS_INCLUDE 0x01 /// /// Audit successful occurrences of the specified event type. This value is valid for the AuditSetPerUserPolicy and /// AuditQueryPerUserPolicy functions. /// /// /// /// PER_USER_AUDIT_SUCCESS_EXCLUDE 0x02 /// /// Do not audit successful occurrences of the specified event type. This value is valid for the AuditSetPerUserPolicy and /// AuditQueryPerUserPolicy functions. /// /// /// /// PER_USER_AUDIT_FAILURE_INCLUDE 0x04 /// /// Audit failed attempts to cause the specified event type. This value is valid for the AuditSetPerUserPolicy and /// AuditQueryPerUserPolicy functions. /// /// /// /// PER_USER_AUDIT_FAILURE_EXCLUDE 0x08 /// /// Do not audit failed attempts to cause the specified event type. This value is valid for the AuditSetPerUserPolicy and /// AuditQueryPerUserPolicy functions. /// /// /// /// PER_USER_AUDIT_NONE 0x10 /// /// Do not audit the specified event type. This value is valid for the AuditSetPerUserPolicy and AuditQueryPerUserPolicy functions. /// /// /// /// public AuditCondition AuditingInformation; /// A GUID structure that specifies an audit-policy category. public Guid AuditCategoryGuid; } /// The POLICY_AUDIT_SID_ARRAY structure specifies an array of SID structures that represent Windows users or groups. [PInvokeData("ntsecapi.h")] [StructLayout(LayoutKind.Sequential)] public struct POLICY_AUDIT_SID_ARRAY { /// The number of SID structures in the UserSidArray array. public uint UsersCount; /// An array of SID pointers. private IntPtr _UserSidArray; /// An array of SID pointers. public PSID[] UserSidArray => _UserSidArray == IntPtr.Zero ? new PSID[0] : _UserSidArray.ToArray((int)UsersCount); } /// Provides a for memory allocated by audit functions that is disposed using . public class SafeAuditMemoryHandle : 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 SafeAuditMemoryHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeAuditMemoryHandle() : base() { } /// /// Extracts an array of structures of containing items. This /// call can cause memory exceptions if the pointer does not have sufficient allocated memory to retrieve all the structures. /// /// The type of the structures to retrieve. /// The number of structures to retrieve. /// The number of bytes to skip before reading the structures. /// An array of structures of . public IEnumerable ToIEnum(int count, int prefixBytes = 0) { if (IsInvalid) return null; if (!typeof(T).IsBlittable()) throw new ArgumentException(@"Structure layout is not sequential or explicit."); return handle.ToIEnum(count, prefixBytes); } /// /// Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter. /// /// The type of the object to which the data is to be copied. This must be a structure. /// A managed object that contains the data that this holds. public T ToStructure() { if (IsInvalid) return default; return handle.ToStructure(); } /// protected override bool InternalReleaseHandle() { AuditFree(handle); return true; } } /// A custom marshaler for functions using memeroy allocated by audit functions so that managed strings can be used. /// internal class AuditStringMarshaler : ICustomMarshaler { public static ICustomMarshaler GetInstance(string _) => new AuditStringMarshaler(); public void CleanUpManagedData(object ManagedObj) { } public void CleanUpNativeData(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return; AuditFree(pNativeData); } public int GetNativeDataSize() => -1; public IntPtr MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException(); public object MarshalNativeToManaged(IntPtr pNativeData) => (string)StringHelper.GetString(pNativeData)?.Clone(); } } }