Private/AuditPolicy.ps1

function Initialize-HLAuditNativeType {
    [CmdletBinding()]
    param()

    if ($script:HLAuditNativeLoaded -or ('HardeningLens.NativeAuditPolicy2' -as [type])) {
        $script:HLAuditNativeLoaded = $true
        return
    }

    $source = @'
using System;
using System.Runtime.InteropServices;
 
namespace HardeningLens
{
    public static class NativeAuditPolicy2
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct AUDIT_POLICY_INFORMATION
        {
            public Guid AuditSubCategoryGuid;
            public UInt32 AuditingInformation;
            public Guid AuditCategoryGuid;
        }
 
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.U1)]
        private static extern bool AuditQuerySystemPolicy(
            [In] Guid[] pSubCategoryGuids,
            UInt32 PolicyCount,
            out IntPtr ppAuditPolicy
        );
 
        [DllImport("advapi32.dll")]
        private static extern void AuditFree(IntPtr buffer);
 
        // Marshalling stays in C# because the PowerShell 5.1 binder can select
        // the PtrToStructure(IntPtr, object) overload and fail at runtime.
        public static AUDIT_POLICY_INFORMATION QuerySinglePolicy(Guid subCategoryGuid)
        {
            IntPtr buffer = IntPtr.Zero;
            bool success = AuditQuerySystemPolicy(new Guid[] { subCategoryGuid }, 1, out buffer);
            if (!success)
            {
                int errorCode = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(
                    errorCode,
                    "AuditQuerySystemPolicy failed with Win32 error " + errorCode + "."
                );
            }
 
            try
            {
                return (AUDIT_POLICY_INFORMATION)Marshal.PtrToStructure(buffer, typeof(AUDIT_POLICY_INFORMATION));
            }
            finally
            {
                AuditFree(buffer);
            }
        }
    }
}
'@


    Add-Type -TypeDefinition $source -Language CSharp -ErrorAction Stop
    $script:HLAuditNativeLoaded = $true
}

function Get-HLAuditPolicySetting {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [guid]$SubcategoryGuid
    )

    Assert-HLWindows
    Initialize-HLAuditNativeType

    $information = [HardeningLens.NativeAuditPolicy2]::QuerySinglePolicy($SubcategoryGuid)
    $raw = [uint32]$information.AuditingInformation
    return [pscustomobject][ordered]@{
        SubcategoryGuid = $SubcategoryGuid.ToString()
        RawValue        = $raw
        Success         = [bool](($raw -band 1) -eq 1)
        Failure         = [bool](($raw -band 2) -eq 2)
        None            = [bool](($raw -band 4) -eq 4)
    }
}

function Invoke-HLAuditPolicyProbe {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [object]$Control
    )

    $parameters = $Control.parameters
    try {
        $setting = Get-HLAuditPolicySetting -SubcategoryGuid ([guid][string]$parameters.subcategoryGuid)
    }
    catch {
        if (Test-HLErrorMatchesCode -Exception $_.Exception -Code 1314, 0x80070522) {
            return Get-HLProbeResult -Status Unknown -Expected (@($parameters.requiredFlags) -join ' and ') -Actual $null -Message 'Querying the advanced audit policy requires an elevated session holding SeSecurityPrivilege. Collect with elevation to resolve this control.'
        }
        throw
    }
    $missing = New-Object System.Collections.Generic.List[string]
    foreach ($requiredFlag in @($parameters.requiredFlags)) {
        if (-not [bool]$setting.$requiredFlag) {
            $missing.Add([string]$requiredFlag)
        }
    }

    $actualFlags = New-Object System.Collections.Generic.List[string]
    if ($setting.Success) { $actualFlags.Add('Success') }
    if ($setting.Failure) { $actualFlags.Add('Failure') }
    if ($actualFlags.Count -eq 0) { $actualFlags.Add('No Auditing') }

    $expected = @($parameters.requiredFlags) -join ' and '
    $actual = $actualFlags.ToArray() -join ' and '
    $evidence = [pscustomobject][ordered]@{
        SubcategoryName = [string]$parameters.subcategoryName
        SubcategoryGuid = [string]$parameters.subcategoryGuid
        RawValue        = $setting.RawValue
        Success         = $setting.Success
        Failure         = $setting.Failure
    }

    if ($missing.Count -eq 0) {
        return Get-HLProbeResult -Status Pass -Expected $expected -Actual $actual -Message 'The effective advanced audit policy contains every required flag.' -Evidence $evidence
    }

    return Get-HLProbeResult -Status Fail -Expected $expected -Actual $actual -Message ('Missing required audit flags: {0}.' -f ($missing.ToArray() -join ', ')) -Evidence $evidence
}