1. Overview

  • Unpatched Binary: acx01000_unpatched.sys
  • Patched Binary: acx01000_patched.sys
  • Overall Similarity: 98.75%
  • Diff Statistics: 1223 matched functions, 13 changed functions, 1210 identical functions, 0 unmatched.
  • Verdict: The patch adds conditional WPP/ETW trace instrumentation to the AfxDataFormatList data-format list operations (add / remove / destroy), gated by a WIL feature flag, and refines de-duplication bookkeeping in the WIL feature-usage reporting cache. The remaining changed functions are WIL feature-staging and feature-configuration-change-notification registration churn plus WPP tracing. No memory-safety vulnerability is fixed or introduced by this patch; the changed list-management functions use consistent structure offsets across both versions.

2. Change Summary

Finding 1: Conditional ETW Instrumentation in AfxDataFormatList Cleanup

  • Severity: Informational (non-security)
  • Class: Telemetry / instrumentation
  • Affected Functions:
  • Acx::AfxDataFormatList::~AfxDataFormatList — unpatched scalar-deleting destructor ??_GAfxDataFormatList @ 0x1C0008ED8, patched ??1AfxDataFormatList @ 0x1C0008B6C
  • Acx::AfxDataFormatList::AddDataFormat @ 0x1C000818C (unpatched) / 0x1C0008D60 (patched)
  • Acx::AfxDataFormatList::RemoveDataFormat @ 0x1C00084B4 (unpatched) / 0x1C00090D0 (patched)

Description: AfxDataFormatList maintains a doubly-linked list of AfxDataFormat pool allocations (pool tag 'AfxD' / 0x44786641) anchored at structure offset +0x30. The insert (AddDataFormat), remove (RemoveDataFormat), and destructor all use offset +0x30 for this list, and they do so identically in both the unpatched and patched binaries. The list offset is unchanged.

The patch adds conditional WPP/ETW trace records around these list operations, gated by Feature_Servicing_Audio_ACXGetNotificationDevice__private_IsEnabledDeviceUsage(). When the feature is enabled, a trace record is emitted as each AfxDataFormat entry is unlinked and freed with ExFreePoolWithTag. This is instrumentation only; the freeing logic and list traversal are otherwise unchanged.

Acx::AfxTargetPin:: scalar deleting destructor (unpatched 0x1C0005368, patched 0x1C0005CF8) is a separate class's destructor that walks its own list at offset +0x80; it uses +0x80 in both versions and is functionally unchanged.

Finding 2: WIL Feature-Usage Reporting Cache De-duplication Refinement

  • Severity: Informational (non-security)
  • Class: Telemetry / feature-staging bookkeeping
  • Affected Function: wil_details_FeatureReporting_RecordUsageInCache (unpatched 0x1C0001ABC / patched 0x1C00022E4)

Description: This is Windows Implementation Library (WIL) feature-usage reporting cache code. It fills a caller-supplied 24-byte report descriptor (a1) and updates the per-feature usage bits held in *a2 via an interlocked compare-exchange loop. In the unpatched version, after the compare-exchange loop the report-descriptor fields at a1+4 (kind = 1), a1+8 (= a3) and a1+12 (= a4) are written unconditionally. The patched version writes those fields only when the usage was not already recorded this session — that is, when the reporting-index is out of range (>= 0x40) or when the "already recorded" flag stored at a1+16 is zero after the loop (a cache miss). On a cache hit the patched build skips re-populating the descriptor, so an already-reported usage is not re-emitted. The bounds written into a1 (offsets 0 through 16) are identical in both builds. This is a de-duplication refinement in WIL's usage-reporting cache; it changes what gets reported to telemetry, not memory safety.

3. Pseudocode Diff

Acx::AfxDataFormatList::~AfxDataFormatList (unpatched 0x1C0008ED8 → patched 0x1C0008B6C)

// UNPATCHED ~AfxDataFormatList (0x1C0008ED8)
void ~AfxDataFormatList(AfxDataFormatList* obj) {
    ListEntry* list_head = (ListEntry*)((char*)obj + 0x30);   // list anchor at +0x30
    while (list_head->Flink != list_head) {
        ListEntry* entry = list_head->Flink;
        UnlinkEntry(entry);
        ExFreePoolWithTag(entry, 'AfxD');                     // free 'AfxD' entry
    }
}

// PATCHED ~AfxDataFormatList (0x1C0008B6C)
void ~AfxDataFormatList(AfxDataFormatList* obj) {
    bool log_enabled = Feature_..._ACXGetNotificationDevice_IsEnabledDeviceUsage();
    ListEntry* list_head = (ListEntry*)((char*)obj + 0x30);   // SAME anchor at +0x30
    while (list_head->Flink != list_head) {
        ListEntry* entry = list_head->Flink;
        if (log_enabled)
            WppTraceFree(entry);                              // NEW: conditional trace record
        UnlinkEntry(entry);
        ExFreePoolWithTag(entry, 'AfxD');
    }
}

4. Assembly Analysis

Patched ~AfxDataFormatList (0x1C0008B6C) — list walk with new instrumentation

0x1c0008c0c: lea     rbx, [rsi+0x30]                     ; list anchor at +0x30 (unchanged)
0x1c0008c10: call    Feature_..._ACXGetNotificationDevice_IsEnabledDeviceUsage
0x1c0008c15: test    eax, eax                            ; feature flag gate for tracing
0x1c0008c71: call    qword [rel __guard_dispatch_icall_fptr]
0x1c0008c7f: call    qword [rel __imp_ExFreePoolWithTag] ; free 'AfxD' entry

The unpatched scalar-deleting destructor at 0x1C0008ED8 performs the same +0x30 list walk and ExFreePoolWithTag free without the feature-gated trace calls.

5. Behavioral Notes

  • The AfxDataFormatList list anchor is +0x30 in both binaries; AddDataFormat, RemoveDataFormat, and the destructor agree on this offset in both versions.
  • The AfxTargetPin destructor uses +0x80 for its own (different) list in both versions; this offset is correct for that class and unchanged.
  • The only functional delta on the AfxDataFormatList path is the addition of feature-gated WPP/ETW trace records.

6. Changed Functions — Full Triage

  • Acx::AfxDataFormatList::~AfxDataFormatList (unpatched 0x1C0008ED8 / patched 0x1C0008B6C, Sim: 0.8058 in the diff pairing): [Informational] Added feature-gated WPP/ETW trace records around the +0x30 'AfxD' list free loop. List offset unchanged.
  • sub_1C00084B4 (RemoveDataFormat) (Sim: 0.9545): [Informational] Added conditional ETW logging when removing/freeing list entries.
  • sub_1C000818C (AddDataFormat) (Sim: 0.9719): [Informational] Added conditional ETW logging when inserting list entries.
  • wil_details_FeatureReporting_RecordUsageInCache (unpatched 0x1C0001ABC / patched 0x1C00022E4, Sim: 0.9808): [Informational] WIL usage-reporting cache now skips re-populating the report descriptor on a cache hit (already-recorded usage). De-duplication bookkeeping; a1 output bounds unchanged.
  • wil_details_FeatureStateCache_TryEnableDeviceUsageFastPath (unpatched 0x1C0001E78 / patched 0x1C00027D0): [Behavioral, non-security] WIL feature-state cache. Unpatched unconditionally set bit 0x10 in the multi-stack-support feature-state word; patched takes the feature-state pointer and kind as parameters and conditionally sets bit 0x10 or 0x20 via an interlocked update. Feature-staging infrastructure, not memory safety.
  • wil_details_FeatureReporting_ReportUsageToServiceDirect (unpatched 0x1C0001D88 / patched 0x1C00025BC): [Behavioral, non-security] WIL usage-reporting. Unpatched hard-coded the feature id 7189701 and the static _reporting global; patched reads the feature id and reporting pointer from its parameters. Same RecordUsageInCache / RtlNotifyFeatureUsage flow, now parameterized. Feature-staging telemetry, not memory safety.
  • sub_1C002EC10 (Sim: 0.8804): [Behavioral] Added cleanup for RtlUnregisterFeatureConfigurationChangeNotification.
  • sub_1C0091790 & sub_1C0090C30 & sub_1C0070620 & sub_1C007C8F0 & sub_1C00A9008 (Sim: 0.88 - 0.94): [Cosmetic] Telemetry notification refactoring and data reference relocations.
  • sub_1C001628C (Sim: 0.9796): [Cosmetic] Register renaming and small ETW updates.

7. Unmatched Functions

There are no added or removed functions. The patch consists entirely of in-place modifications.

8. Confidence & Caveats

  • Confidence: High. Both the unpatched (0x1C0008ED8) and patched (0x1C0008B6C) AfxDataFormatList destructors walk the +0x30 list and free 'AfxD' entries; the patched version differs only by feature-gated trace calls. AddDataFormat/RemoveDataFormat use +0x30 in both versions. AfxTargetPin's destructor (0x1C0005368 unpatched / 0x1C0005CF8 patched) uses +0x80 in both versions.