Drivers32:媒体编解码与驱动映射

📅 2026/7/24 21:22:32
Drivers32:媒体编解码与驱动映射
Drivers32媒体编解码与驱动映射这个程序的功能是在不写入注册表、不加载任何媒体模块的前提下分别读取 64 位和 32 位Drivers32映射输出每条映射的来源、值名、注册表类型和原始数据。要完成这项只读核查分为四步确定 64 位与 32 位 Drivers32 映射来源。以只读权限打开来源键并测量枚举缓冲区容量。按索引枚举全部值并在缓冲区不足时重试。按注册表类型解释数据再输出可复查的记录。输入来自HKLM\Software\Microsoft\Windows NT\CurrentVersion\Drivers32及其WOW6432Node对应位置。Windows 注册表由注册表管理器维护用键和值保存系统和软件配置。Drivers32的值名保存媒体类别或编解码器标识值数据保存关联的模块文本。程序从两个来源读取原始值最后得到带来源标签的只读映射记录。64 位 Drivers32 与 32 位 Drivers32 - 打开并测量键 - 枚举值名和原始字节 - 按类型显示记录一、第一步确定 64 位与 32 位 Drivers32 映射来源第一步要区分两份配置来源。Drivers32保存媒体类别或编解码器标识到模块文本的映射。应用或多媒体框架根据格式提出处理请求ACM 或 VCM 等组件再选择适合的模块。此处读取到的是注册表配置文件是否存在和模块是否已加载需要另行验证。媒体格式信息 - 应用或多媒体框架提出处理请求 - ACM 或 VCM 查询登记能力 - Drivers32 返回模块文本1. 媒体播放需要把格式标识映射到处理模块Drivers32 用于把媒体格式标识映射到处理模块。音频和视频文件包含编码格式、采样率、通道数、帧大小等信息应用程序或 Windows 多媒体组件需要根据格式找到合适的处理器。早期 Windows 多媒体架构使用驱动和编解码器模块提供波形音频、MIDI、音频压缩和视频压缩能力。Drivers32是保存这类“媒体类别或格式标识映射到模块文本”关系的注册表位置。值名表达类别或编码器身份值数据表达关联模块。它不用于保存进程启动列表也不等同于设备管理器列出的物理硬件驱动列表。枚举结果应按映射关系解释。媒体数据格式标识 - Windows 多媒体组件查询 Drivers32 - 值名类别或编解码器标识 - 值数据模块文本 - 对应的媒体处理模块2. 常见值名前缀表达不同媒体接口类别值名需要按媒体接口类别解释。wave、midi等名称可对应传统波形音频或 MIDI 类别。msacm.*常与 Audio Compression ManagerACM标识有关。vidc.*常与 Video Compression ManagerVCM格式标识有关。具体前缀和后缀应保留原文因为它们可能携带 FOURCC 或兼容性信息。值数据可能是wdmaud.drv、msacm32.drv、.acm文件名、.dll文件名或完整路径。没有目录的文件名不能直接与当前工作目录拼接。它表示模块文本后续若要查找文件必须说明使用了哪一种系统模块定位规则。3. 32 位映射与 64 位映射应作为不同配置来源旧式媒体模块也受进程位数约束。32 位应用程序和 64 位应用程序不能在同一进程中加载彼此架构不匹配的模块。Windows 因此可能在标准路径和WOW6432Node路径保存两份 Drivers32 映射。即使同一个值名和模块文本在两处都出现也应保留两条记录及其来源标签。一个来源缺失、一个来源为空、一个来源有值是三种不同的观察结果。不以一个视图的内容填补另一个视图。4. 注册表映射与模块实际使用状态彼此独立读取结果需要控制结论范围。枚举到某个 Drivers32 值能证明注册表中存在这条映射不能单独证明文件仍存在、模块架构与当前进程匹配、模块已被加载或当前媒体文件正在使用该编解码器。本次读取只保存注册表事实包括原始映射文本、来源键和视图标签。文件属性、PE 架构、签名状态和运行时模块证据属于其它检查阶段每个阶段只说明自己实际观察到的内容。5. 映射记录需要保留可复查的字段集合每条映射都要能回到原始来源。一个完整记录包含完整注册表键路径、逻辑架构标签、值名、值类型、原始字节长度和可验证时的解码文本。相同模块文本被多个类别引用时值名仍然保留。同一类别在不同架构来源出现时来源路径仍然保留。下面的两条记录看起来使用同一模块实际回答的是不同问题来源64 位 Drivers32 值名wave 模块文本wdmaud.drv 来源32 位 Drivers32 值名wave 模块文本wdmaud.drv第一条和第二条并不能互相替代。它们分别来自可重定向注册表的不同位置面对的应用程序架构也不同。将它们去重后只能知道某个文本曾出现无法再确定它对哪个配置范围有意义。6. 模块文本先按原文保留模块文本可能是完整路径也可能只有文件名。读取阶段不按当前工作目录拼接路径也不加载该文件。程序将能确认的字符串原文连同类型和来源输出避免把没有依据的文件定位结果写成配置事实。后续文件检查需要单独说明定位规则。候选路径不存在、打开被拒绝、目标是目录、PE 格式无效、架构不匹配和签名校验失败都是独立结果不应混入本次注册表枚举结论。7. 驱动文件、用户态模块和内核驱动不是同一个概念文件扩展名不能直接等同于运行层级。Drivers32 中可能看到.drv、.acm、.dll或完整路径文本。它们表达的是传统多媒体组件使用的模块名称或文件位置。这些模块通常由用户态多媒体子系统按相应接口加载。内核驱动则由服务控制管理器和内核 I/O 路径管理具有不同的加载时机、签名要求、内存地址空间和 IRQL 运行约束。.drv是历史 Windows 驱动模型常用的模块扩展名文件本身可能仍是用户态 PE 映像。.acm常用于音频压缩管理器组件。.dll是动态链接库的常见扩展名。扩展名帮助读者理解注册惯例却不能独立证明一个文件是可加载 PE、当前已加载模块或内核态代码。本次程序不检查 PE 头、文件签名和实际模块列表只读取 Drivers32 映射。8. ACM、VCM 与应用程序之间通过格式协商连接编码格式和模块加载动作需要连贯理解。ACMAudio Compression Manager音频压缩管理器为传统音频格式转换提供统一接口。应用或多媒体组件提出源格式、目标格式和转换操作ACM 根据注册的驱动能力寻找可处理的组件。VCMVideo Compression Manager视频压缩管理器承担类似的视频编解码协商工作vidc.*这类标识常与视频格式代码关联。格式协商由调用方先描述媒体格式再由对应管理器选择满足能力、架构和配置条件的模块。模块名称只是候选信息实际选择还受系统组件版本、已注册编解码器能力、进程位数和调用接口影响。完成第一步后已经获得两份不能相互替代的来源路径和架构标签。接下来需要以只读方式打开每个来源并取得枚举缓冲区的初始容量。二、第二步以只读权限打开来源键并测量枚举容量第二步要取得可查询的键句柄。HKEY是注册表管理器返回的已打开键句柄代表当前进程对一个键的访问引用。打开成功后调用方负责用RegCloseKey释放该引用。预定义根键HKEY_LOCAL_MACHINE由系统管理不能关闭。打开父键后RegQueryInfoKeyW可给出当前值数量、最长值名和最大数据长度。这些数字只用于第一次分配缓冲区。值数量是提示值枚举期间配置可能变化所以后续仍要处理实际返回的长度。ERROR_ACCESS_DENIED表示当前令牌没有获得查询权限。ERROR_FILE_NOT_FOUND表示来源键在本次读取时不存在。程序将状态与完整键路径和视图标签一起输出读者可以区分权限不足和配置缺失。1. 一条记录要能回答“来自哪里、是什么、读取到了什么”输出要避免把多个阶段拼成单个结论。一条可复查的 Drivers32 记录包含根键、路径、视图、值名、REG 类型和原始字节。文本解释严格按照 API 返回的长度进行不展开环境变量也不追加文件检查结果。当记录显示msacm.msg711对应msg711.acm时含义是“当前来源键里有这项映射”。它不能证明文件当前可用、某个进程已加载它或某段音频由它解码。将注册表事实和其它证据分开呈现记录的适用范围才清楚。2. HKEY、访问掩码和缓冲区是注册表 API 的三类基础对象调用注册表 API 前要理解资源和权限。HKEY是注册表管理器返回的已打开键句柄它代表当前进程在指定键上的一次访问引用。RegOpenKeyExW成功后调用方拥有这份引用必须调用RegCloseKey释放。预定义根键如HKEY_LOCAL_MACHINE由系统提供不能关闭。REGSAM是注册表访问掩码类型。KEY_QUERY_VALUE允许读取值KEY_ENUMERATE_SUB_KEYS允许读取直接子键名KEY_WOW64_64KEY和KEY_WOW64_32KEY指定要访问的软件注册表视图。只读枚举只申请必需权限权限不足时保留ERROR_ACCESS_DENIED不通过写入、提升或切换视图掩盖失败。名称缓冲区和数据缓冲区的单位不同。RegEnumValueW的lpcchValueName使用 UTF-16 宽字符数lpcbData使用字节数。同一个DWORD变量不能同时保存这两种容量。值名与值数据也是不同字段媒体类别的值名和模块文本的数据需要同时保存。3. 标准读取先打开、再测量、再枚举、最后关闭枚举时所有成功资源都要在失败路径释放。下面的最小流程先请求只读权限使用两个独立容量变量然后在ERROR_NO_MORE_ITEMS正常结束时关闭键。示范中的nameCapacity是wchar_t个数dataCapacity是字节数。缓冲区只在调用期间使用成功后以 API 返回的实际长度构造记录。HKEY keynullptr;constLSTATUS openStatusRegOpenKeyExW(HKEY_LOCAL_MACHINE,// 输入机器范围根键。系统所有不由本段关闭。drivers32Path,// 输入NUL 结尾 UTF-16 Drivers32 相对路径。0,// 输入保留必须为 0。KEY_QUERY_VALUE,// 输入仅枚举值所需的最小权限。key);// 输出成功时得到 HKEY本段负责 RegCloseKey。if(openStatusERROR_SUCCESS){for(DWORD index0;;index){std::vectorwchar_tname(256,L\0);// 名称容量单位为 wchar_t。std::vectorBYTEdata(1024);// 数据容量单位为字节。DWORD nameCapacitystatic_castDWORD(name.size());DWORD dataCapacitystatic_castDWORD(data.size());DWORD typeREG_NONE;constLSTATUS statusRegEnumValueW(key,index,name.data(),nameCapacity,nullptr,type,data.data(),dataCapacity);if(statusERROR_NO_MORE_ITEMS)break;if(statusERROR_MORE_DATA){// 正确处理是分别扩容 name 和 data 后重试同一 index。不能把它当作枚举结束。continue;}if(status!ERROR_SUCCESS){// 记录 index、来源路径和 status继续下一项。不把失败值当成空字符串。continue;}// 此处仅使用 nameCapacity 个 UTF-16 字符与 dataCapacity 个原始字节创建一条映射记录。}RegCloseKey(key);// 释放本段成功打开的 HKEY。关闭后 key 不能再传给任何注册表 API。}下面的错误把ERROR_MORE_DATA当成“没有下一个值”会在第一个较长名称或较大数据处截断整个枚举。错误发生在混淆“缓冲区不足”和“正常结束”这两种返回状态。if(RegEnumValueW(key,index,name,nameChars,nullptr,type,data,dataBytes)!ERROR_SUCCESS){break;// 错误ERROR_MORE_DATA 需要扩容重试ERROR_NO_MORE_ITEMS 才是正常结束。}完成第二步后已经得到两个来源各自的只读HKEY与首次分配所需的容量。接下来要按索引读取每个值并在系统返回容量不足时重试同一个索引。三、第三步按索引枚举全部值并处理缓冲区不足第三步要从每个已经打开的来源键读取全部值。本机 Drivers32 与WOW6432NodeDrivers32 分别枚举记录保留完整键路径和架构标签。相同值名或相同模块文本不能用来合并记录。// 意义打开注册表子键。// 返回ERROR_SUCCESS 表示成功。其它返回值是 Win32 错误码。// 成功时 phkResult 接收 HKEY调用方必须关闭。LSTATUSRegOpenKeyExW(HKEY hKey,LPCWSTR lpSubKey,DWORD ulOptions,REGSAM samDesired,PHKEY phkResult);// 意义关闭打开成功的注册表键句柄。// 返回ERROR_SUCCESS 表示成功。LSTATUSRegCloseKey(HKEY hKey);constwchar_t*sources[]{LSoftware\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32,LSoftware\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32,};模块文本可能是wdmaud.drv、msacm32.drv、.acm文件名、.dll文件名或完整路径。读取阶段先保留原文不按普通启动命令切分空格。1. 枚举所有值时保持名称、类型和原始字节Drivers32 使用值枚举结构。值名如wave、midi、vidc.*、msacm.*表示类别或编码器标识值数据才是对应模块文本。// 意义查询键中的值数、最大值名长度和最大值数据长度。// 返回ERROR_SUCCESS 表示成功。值名长度单位是 wchar_t 个数// 值数据长度单位是字节。LSTATUSRegQueryInfoKeyW(HKEY hKey,LPWSTR lpClass,LPDWORD lpcchClass,LPDWORD lpReserved,LPDWORD lpcSubKeys,LPDWORD lpcbMaxSubKeyLen,LPDWORD lpcbMaxClassLen,LPDWORD lpcValues,LPDWORD lpcbMaxValueNameLen,LPDWORD lpcbMaxValueLen,LPDWORD lpcbSecurityDescriptor,PFILETIME lpftLastWriteTime);// 意义按索引读取一个 Drivers32 值。// 返回ERROR_SUCCESS 表示成功。ERROR_NO_MORE_ITEMS 表示结束。// ERROR_MORE_DATA 表示值名或数据容量不足。LSTATUSRegEnumValueW(HKEY hKey,DWORD dwIndex,LPWSTR lpValueName,LPDWORD lpcchValueName,LPDWORD lpReserved,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData);正确代码让值名和数据使用不同缓冲区。ERROR_MORE_DATA时分别扩大 UTF-16 名称缓冲区和字节数据缓冲区避免单位混淆。std::vectorwchar_tname(maxNameChars1,L\0);std::vectorBYTEdata(maxDataBytes);DWORD nameCharsstatic_castDWORD(name.size());DWORD dataBytesstatic_castDWORD(data.size());DWORD typeREG_NONE;LSTATUS statusRegEnumValueW(key,index,name.data(),nameChars,nullptr,type,data.empty()?nullptr:data.data(),dataBytes);if(statusERROR_SUCCESS){std::wstringmediaClass(name.data(),nameChars);data.resize(dataBytes);}字符串值只在REG_SZ或REG_EXPAND_SZ且字节数能被sizeof(wchar_t)整除时转换。其它类型保留原始类型和字节数避免把错误数据展示为模块路径。// 错误示例只根据模块文本建立记录。// 多个媒体类别可以映射到同一个 wdmaud.drv类别身份会丢失。record.moduledecodedText;完成第三步后已经取得每条映射的值名、类型和实际返回的字节长度。接下来需要依照注册表类型判断哪些数据可以安全显示为文本或数值哪些数据只能保留原始长度。四、第四步按注册表类型解释数据并输出记录第四步要让输出保持准确。REG_SZ和REG_EXPAND_SZ通常保存 UTF-16 文本。程序仅在实际字节数能被sizeof(wchar_t)整除时将它们显示为文本并在末尾确有结束 NUL 时移除一个 NUL。REG_DWORD仅在原始数据正好为 4 字节时显示为无符号数。其它类型保留类型名和原始字节数不将未知数据猜成模块路径。显示文本前还要转义 NUL、回车和换行。这样控制字符不会截断控制台行也不会伪造额外的输出记录。每条输出同时保留来源、视图、值名和类型读取结果可以回到相应注册表位置复查。模块文本是映射数据完整路径、文件存在性、映像架构和签名验证需要后续独立步骤。wdmaud.drv这类名称没有目录直接按当前工作目录拼接会产生无依据的路径。完成第四步后得到的是 Drivers32 的只读配置记录。该记录说明映射在读取时存在不能独立证明模块已加载或媒体数据已经被成功处理。完整可运行程序在附件https://wangweicm.lanzouu.com/ivw2h3yewjad