| name | maintain-dwm-offsets |
| description | Audit, compare, and maintain OpenGlass dwmcore.dll and uDWM.dll Layout and Symbol schemas with paired PE/PDB identity and IDA evidence. Use when investigating a new Windows DWM binary, checking one projection member, vtable slot, complete symbol name, or hook, comparing exact builds or revisions, validating legacy or milcomp projection metadata, or preparing evidence-backed schema changes. |
Maintain DWM projections
Treat a Layout offset or Symbol match as verified only when its semantic role is demonstrated in the selected binary. Do not infer schema data from a Windows marketing name, image size, nearby members, or a previous build.
Select the scope
- Identify the requested module:
dwmcore.dll, uDWM.dll, or both.
- Identify the requested depth:
- Projection item: verify only named schema IDs and their direct dependencies.
- Build comparison: verify the same IDs in every selected sample.
- Module audit: enumerate every schema item consumed by that module.
- Full audit: audit both modules and all loaded samples. Do this only when explicitly requested.
- Require the DWM architecture:
legacy or milcomp. Confirm its actual consumers and read architectures.md. Never infer architecture from the Git branch, marketing version, or symbol name.
- Route the stable ID to the matching inventory. For a Layout, run
python .agents/skills/maintain-dwm-offsets/scripts/validate_projection_layouts.py . --architecture legacy|milcomp --module udwm|dwmcore --id STABLE_ID. For a Symbol or hook, run python .agents/skills/maintain-dwm-offsets/scripts/validate_projection_symbols.py . --architecture legacy|milcomp --module udwm|dwmcore --id STABLE_ID; do not pass a Symbol ID to the Layout validator. Run the other validator without --id only when that inventory or a direct dependency is also in scope. Each selected module schema is still fully validated.
Do not silently expand a focused request into a full audit. Do not modify an IDB or production schema unless the user explicitly asks for those changes. Files under $(IntDir)\Generated\Projection are disposable build artifacts and must never be edited.
Establish evidence
Read evidence.md for sample identity, interval semantics, confidence levels, cross-validation, and the report contract. Read ida-workflow.md before operating IDA through MCP.
For each sample:
- Record module, architecture, path, hash, PE/file version when available, and PDB identity when available.
- Treat folder names and labels such as
25H2 or 26H1 as hints until binary metadata corroborates them.
- For a Layout, after establishing the exact PE build and revision, run the Layout validator with
--version BUILD.REVISION (or the full 10.0.BUILD.REVISION) and record the selected schema ID, interval, entry, and raw offset expression. This versioned run also performs structural validation, so it replaces rather than duplicates the initial inventory command. Do not choose a case by eye.
- For a Symbol, run
python Scripts/audit_symbol_resolution.py . --architecture legacy|milcomp --module udwm|dwmcore --version BUILD.REVISION --image PATH_TO_DLL --symbol-path PATH_TO_SYMBOLS [--configuration release|debug] [--dbghelp PATH_TO_DBGHELP] [--id STABLE_ID]. The default configuration is Release, so Debug-only logical Symbols remain inactive. Record the selected binding index, binding interval, matched complete name, and RVA, plus the selected DbgHelp path, version, and hash and the PDB identity and hash because exact UNDNAME_COMPLETE text is resolver-version input. Only a CodeView GUID/age-matched PDB and matching PE version is production name evidence. An unpaired PDB is discovery-only. Discovery can still return a successful process exit when the requested names resolve; automation making a production claim must require evidence: production_candidate and pdb.paired: true, not merely exit code zero.
For fast discovery before a schema audit, use python Scripts/dump_symbols.py --input IMAGE [--output SYMBOL_CACHE] [--grep TEXT]. The cache defaults to %TEMP%\symbols; the command downloads the image-matched public PDB and prints complete names, but does not replace the identity-rich audit report.
To check every indexed x64 revision of a Windows build, run python Scripts/audit_winbindex_revisions.py . --architecture legacy|milcomp --module udwm|dwmcore --build BUILD. The command verifies downloaded image hashes, PE/PDB identity, and exact symbol names; --list-only only inventories revisions. The result is a symbol-resolution check, not semantic or runtime evidence.
For the built-in catalog, freeze inventory and collect evidence with python Scripts/maintain_symbol_catalog.py inventory ., collect, and verify. Production collect requires an explicit Windows Debugging Tools --dbghelp and attempts only exact x64 Winbindex candidates available from Microsoft's symbol server. It writes the full transient failure detail to without adding failed candidates to the runtime catalog. Symbol-server identity-key collisions are preserved structurally in ; paired-PDB 404s and deterministic Symbol/RVA rejections are preserved in . Static binds both reports to the frozen inventory and requires every candidate to appear exactly once in the catalog, collision report, or exclusion report. PDB acquisition must validate the CodeView GUID/age after either direct download or compressed expansion. Frozen Winbindex inventory is maintenance input only and must not participate in ordinary projection code generation. Each architecture index owns one exact DbgHelp version/hash for every record; mixing resolver outputs is forbidden. Changing resolver requires , which clears every existing shard before recollecting the complete architecture catalog; deleting an index while non-empty shards remain is rejected. The committed indexes list every module/build shard explicitly; each shard contains only verified resolvable records and inherits architecture, module, build, and resolver from its index. Each included PE/PDB identity owns a complete Required stable-ID/name/RVA map; absent Optional IDs are unresolved, and codegen derives address class from Symbol kind. Never compress records with deltas, shared resolution sets, packed fields, or cross-revision bases. Source validation proves the included records and complete candidate classification, not semantic or real-OS correctness.
For dwmcore-specific anchors and fallbacks, read dwmcore.md. For uDWM-specific anchors and class transitions, read udwm.md. Read only the relevant module reference for a focused request.
Propose changes safely
Before editing a Layout or Symbol schema item:
- Confirm the user requested implementation rather than analysis only.
- Re-read
OpenGlass/ProjectionSchemas/<architecture>/README.md, OpenGlass/ProjectionHelper.hpp, and the target item's notes. Treat useful reverse-engineering notes as evidence metadata: retain semantic anchors, constructor or xref routes, adjusted-this, ABI traps, ICF/inlining ambiguity, and cross-check guidance verbatim unless new semantic evidence explicitly corrects it. Do not add notes that merely restate an exact PDB name, range, visibility, ordinary consumer, or migration provenance.
- Edit only
OpenGlass/ProjectionSchemas/<architecture>/udwm.json or dwmcore.json. Keep its stable id/name; never hand-edit generated C++ or add a manual projection array/binding step.
- Express Layout right boundaries as exact
until: { build, revision } objects. Use otherwise: true only when the Layout remains valid for the open-ended interval. Without it, later versions resolve to unsupported; do not equate that mechanically with feature removal.
- Preserve every
offset expression as C++ source text, including negative values and sizeof arithmetic. Never evaluate or simplify it in Python.
- Store only the exact, unmodified
UnDecorateSymbolName(..., UNDNAME_COMPLETE) output in each binding's symbol_names. Multiple names within one binding may describe historical aliases only when their typed ABI is identical. Merge versioned entries into one logical Symbol only when module, semantic target, kind/usage, requirement, fallback, and underlying ABI are identical; represent their exact names and non-overlapping intervals as bindings. Keep ABI changes as separate typed logical Symbols even when their intervals are mutually exclusive. Raw Symbols must use their exact function-pointer type; reserve BYTE* plus usage: "code_address" for instruction-pattern anchors. The only projected compatibility exceptions are explicit, typed discard_return and extra_trailing_argument logical Symbols verified by codegen; do not use them for reordered or removed arguments. Never use name-only, substring, decorated-name, or first-match fallbacks.
- A projected Optional or version-inactive function requires an ABI-compatible schema fallback. Declare wrappers
inline and keep their bodies as pure OPENGLASS_MUSTTAIL return Projection::Invoke<&Target>(...) dispatches. Normal Release/LTCG may inline the wrapper. Do not use : it is not a guarantee and produces C4714 warnings when MSVC refuses it. Musttail is Release-only because MSVC cannot guarantee it under Debug . Fallback/range logic belongs in schema bindings and cold commit code. A wrapper is not itself a consumer: require a real runtime call site or a direct typed Symbol consumer such as a Detour, and delete unused wrappers/descriptors instead of retaining unnecessary Required gates.
An open-ended Layout case or Symbol binding is runtime behavior, not evidence that it is correct for an unanalyzed future build.
When preparing a support claim or release, read release-validation.md. Static schema validation, a successful build, and an IDA semantic audit do not replace real-OS validation.
Report
Always return these sections, even for a single projection item:
- Samples: module, architecture, hashes, verified version/PDB data, and unverified labels.
- Schema selection: architecture and requested build/revision; for a Layout, the selected schema ID, entry and interval or
unsupported; for a Symbol, the selected logical ID, binding index and interval, status, matched complete name and RVA, or inactive when no binding covers the version. Use not applicable when the audited item has no corresponding selection.
- Evidence: functions or call chains used and how each value was derived.
- Findings: verified values, exact complete-name resolution, feature/class presence, and comparisons.
- Unverified: missing anchors, ICF ambiguity, inlining ambiguity, or metadata gaps.
- Suggested schema: exact Layout cases or logical Symbol binding/name/range/fallback changes; keep ABI-changing alternatives as separate typed logical Symbols and do not emit edits unless requested.
- Runtime validation:
not run, passed, or failed; IDA-only work normally reports not run.
For an implemented change, also report generator/validator/test/build/audit results and confirm whether any IDB was modified.