# 动态偏移功能接入步骤

本文记录在 KswordARK 中新增“依赖私有结构偏移”的 R0 功能时的通用流程。目标是保证字段 ID、PDB profile、R0 capability、R3 UI 和消费代码一致，避免驱动在无精确 profile 时猜偏移。

## 1. 明确字段和能力边界

1. 确定目标结构、字段和消费场景，例如 `_EPROCESS.Token`、`_TOKEN.UserAndGroups`。
2. 区分“必需字段”和“可选诊断字段”。必需字段缺失时功能必须关闭；可选字段只影响展示或增强信息。
3. 在 `shared/driver/` 中追加新的 `KSW_CAP_*` 能力位。不要复用无关能力位。
4. 字段 ID 只追加，不重排旧编号，保证旧 profile/pack 兼容。

## 2. 更新共享协议

修改 `shared/driver/KswordArkDynDataIoctl.h`：

- 追加 `KSW_DYN_FIELD_ID_*`。
- 更新 `KSW_DYN_FIELD_ID_MAX`。
- 如字段数量超过旧上限，调整 `KSW_DYN_PROFILE_MAX_FIELDS`、`KSW_DYN_PROFILE_EX_MAX_ITEMS` 或 `KSW_DYN_V4_MAX_ITEMS_PER_MODULE`。
- 给新增字段区域写明来源、用途和兼容性说明。

## 3. 更新 R0 DynData 状态

修改以下文件：

- `KswordARKDriver/include/ark/ark_dyndata.h`
  - 在 `KSW_DYN_KERNEL_OFFSETS` 或对应模块 offset 结构里新增 offset 成员。
  - source 结构复用同名成员，保持 offset/source 成对存在。
- `KswordARKDriver/src/features/dyndata/dyndata_loader.c`
  - 初始化新成员为 `KSW_DYN_OFFSET_UNAVAILABLE`。
  - 在 field-id 到 offset/source 指针映射函数中新增 `case`。
- `KswordARKDriver/src/features/dyndata/dyndata_validate.c`
  - 在 `g_KswordDynFieldBindings` 增加字段 descriptor。
  - 在 source 查询 switch 中增加新字段。
  - 在 `KswordARKDynDataComputeCapabilities` 中按必需字段计算 `KSW_CAP_*`。

## 4. 更新 PDB 生成和发布工具

至少同步：

- `tools/pdb_offset_generator/ksword_pdb_profile_generator.py`
  - `FIELD_MAP` 增加 profile 字段名到 PDB 类型/成员的映射。
- `tools/pdb_offset_generator/ksword_ntos_pdb_deep_offsets.py`
  - `KSWORD_ITEM_ALIASES` 增加 deep-offset 别名，方便审计和批量核对。
- `tools/pdb_offset_generator/ksword_profile_release_sync.py`
  - `KNOWN_FIELD_IDS` 增加新字段名和共享 ID。
- 如有覆盖审计脚本，加入关键字段检查项。

生成或发布 profile 后，要确认新字段实际进入 `ark_dyndata_pack_v3.json` 或散装 profile。只改驱动而不更新 profile，R0 必须保持失败关闭。

## 5. 更新 R3 UI 和加载器

修改 `Ksword5.1/Ksword5.1/KernelDock/`：

- capability 显示表加入新 `KSW_CAP_*`。
- profile 字段名字典加入短名和 PDB 全名，例如 `TokUserAndGroups` 与 `_TOKEN.UserAndGroups`。
- 如果功能页会展示缺失能力，补充用户可读说明。

Dock UI 不直接调用 KswordARK `DeviceIoControl`；新增设备访问仍通过 `Ksword5.1/Ksword5.1/ArkDriverClient/`。

## 6. 编写 R0 消费代码

R0 读写私有字段时必须满足：

1. 先 `KswordARKDynDataSnapshot`，只使用快照。
2. 检查 capability 和每个必需 offset。
3. 对写操作优先要求字段 source 为 `KSW_DYN_FIELD_SOURCE_PDB_PROFILE`，不要使用猜测或旧静态偏移。
4. 对来自内核对象的指针、数组索引和长度做边界检查。
5. 使用 `__try/__except` 包裹私有内存访问。
6. 写指针字段前确认生命周期；能原地覆盖就不要把私有结构指针指向栈或临时池内存。
7. 失败时返回明确 `NTSTATUS`，不要静默降级成成功。

## 7. 构建和验证清单

- 驱动 Release 构建通过。
- 用户态 Release 构建通过，特别是共享头更新后的 Qt 项目。
- 新 profile/pack 通过 release sync 校验。
- KernelDock DynData 页能看到字段 present/source/capability。
- 无 profile 或 profile 不匹配时，私有字段功能关闭并返回可解释错误。
- 有 profile 时，功能路径日志能区分 API 成功、API 失败后私有偏移成功、私有偏移校验失败。
