ReactOS 图形系统分析(13):驱动对象 — DRIVEROBJ
ReactOS 图形系统分析13驱动对象 — DRIVEROBJ1. 概述DRIVEROBJ驱动对象位于win32ss/gdi/eng/driverobj.c实现与driverobj.h定义是 GDI 引擎提供的驱动私有数据对象机制。它让显示驱动能创建一个关联到设备HDEV的 GDI 对象携带驱动私有数据pvObj和资源清理回调pFreeProc由 GDI 对象管理器统一管理生命周期。GDI 对象管理器 (句柄表) ↓ GDI_OBJECT_TYPE_DRIVEROBJ EDRIVEROBJ (扩展驱动对象 ← 本分析对象) ├── BASEOBJECT (句柄/锁/引用) ├── DRIVEROBJ (DDI 公开部分) │ ├── pvObj → 驱动私有数据 │ ├── pFreeProc → 释放回调 │ ├── hdev → 关联设备 │ └── dhpdev → 驱动设备句柄 └── reserved作用显示驱动调用EngCreateDriverObj创建对象如私有缓存、资源句柄当对象被删除时引擎自动调用pFreeProc清理——即使驱动忘记释放对象管理器回收时也会兜底清理。2. 核心数据结构2.1 DRIVEROBJDDK 公开结构[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h#L408-L413)typedefstruct_DRIVEROBJ{PVOID pvObj;// 驱动私有数据指针FREEOBJPROC pFreeProc;// 释放回调对象删除时调用HDEV hdev;// 关联的引擎设备句柄PDEVOBJDHPDEV dhpdev;// 驱动设备句柄}DRIVEROBJ;FREEOBJPROC 回调原型typedefBOOL(*FREEOBJPROC)(DRIVEROBJ*pdo);驱动在回调中释放pvObj指向的资源返回 TRUE 表示成功。2.2 EDRIVEROBJ引擎内部扩展[driverobj.h](file:///d:/reactos/win32ss/gdi/eng/driverobj.h#L4-L11)typedefstruct_EDRIVEROBJ{BASEOBJECT baseobj;// GDI 对象头句柄/锁/标志DRIVEROBJ drvobj;// DDI 公开部分PVOID reserved;// 保留}EDRIVEROBJ,*PEDRIVEROBJ;2.3 分配/锁定宏/* 从 GDI 句柄表分配类型 GDI_OBJECT_TYPE_DRIVEROBJ / GDIObjType_DRVOBJ_TYPE */#defineDRIVEROBJ_AllocObjectWithHandle()\((PEDRIVEROBJ)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DRIVEROBJ,sizeof(EDRIVEROBJ)))#defineDRIVEROBJ_UnlockObject(pdo)GDIOBJ_vUnlockObject((POBJ)pdo)/* 尝试锁定返回 NULL 表示对象不存在/被独占 */FORCEINLINE PEDRIVEROBJDRIVEROBJ_TryLockObject(HDRVOBJ hdo){return(PEDRIVEROBJ)GDIOBJ_TryLockObject(hdo,GDIObjType_DRVOBJ_TYPE);}3. 核心函数分析3.1 创建 — EngCreateDriverObjHDRVOBJ APIENTRYEngCreateDriverObj(PVOID pvObj,FREEOBJPROC pFreeObjProc,HDEV hdev){PDEVOBJ*ppdev(PDEVOBJ*)hdev;/* 1. 从 GDI 句柄表分配 EDRIVEROBJ */pedoDRIVEROBJ_AllocObjectWithHandle();if(!pedo)returnNULL;hdopedo-baseobj.hHmgr;// 句柄/* 2. 填充字段 */pedo-drvobj.pvObjpvObj;// 驱动私有数据pedo-drvobj.pFreeProcpFreeObjProc;// 释放回调pedo-drvobj.hdevhdev;// 设备句柄PDEVOBJ 指针pedo-drvobj.dhpdevppdev-dhpdev;// 从 PDEV 取驱动设备句柄/* 3. 解锁并返回句柄 */DRIVEROBJ_UnlockObject(pedo);returnhdo;}要点hdev参数实际是PDEVOBJ指针HDEV 类型从中直接取dhpdev填入——驱动无需自己传。3.2 删除 — EngDeleteDriverObjBOOL APIENTRYEngDeleteDriverObj(HDRVOBJ hdo,BOOL bCallBack,BOOL bLocked){/* 1. 锁定对象获取指针 */pedoDRIVEROBJ_TryLockObject(hdo);if(!pedo)returnFALSE;/* 2. bCallBackTRUE 时手动调用释放回调 */if(bCallBack){if(!pedo-drvobj.pFreeProc(pedo-drvobj))// 回调失败则中止{DRIVEROBJ_UnlockObject(pedo);returnFALSE;}}/* 3. 清空回调防止对象回收时再次调用双释放保护 */pedo-drvobj.pFreeProcNULL;/* 4. bLockedTRUE 时调用者已持锁需额外解锁 */if(bLocked)DRIVEROBJ_UnlockObject(pedo);/* 5. 删除对象此后对象回收不会再调 pFreeProc */GDIOBJ_vDeleteObject(pedo-baseobj);returnTRUE;}双释放保护删除时先把pFreeProc置 NULL这样即使bCallBackFALSE未调用回调对象回收阶段DRIVEROBJ_vCleanup也不会重复调用。3.3 锁定 — EngLockDriverObj / EngUnlockDriverObjPDRIVEROBJ APIENTRYEngLockDriverObj(HDRVOBJ hdo){pedoDRIVEROBJ_TryLockObject(hdo);returnpedo?pedo-drvobj:NULL;// 返回 DDI 公开部分}BOOL APIENTRYEngUnlockDriverObj(HDRVOBJ hdo){/* 先锁定取得 cExclusiveLock 计数 */pedoDRIVEROBJ_TryLockObject(hdo);cLockspedo-baseobj.cExclusiveLock;DRIVEROBJ_UnlockObject(pedo);/* 若之前未持锁计数 2解锁不匹配则失败 */if(cLocks2)returnFALSE;DRIVEROBJ_UnlockObject(pedo);// 第二次解锁returnTRUE;}要点锁计数实现——EngLockDriverObj加 1 次锁EngUnlockDriverObj需要对象已被锁计数 ≥ 2即已锁 本次临时锁才允许解锁防止不平衡的解锁。3.4 清理回调 — DRIVEROBJ_vCleanup对象被 GDI 对象管理器回收时调用VOID NTAPIDRIVEROBJ_vCleanup(PVOID pObject){PEDRIVEROBJ pedopObject;pFreeProcpedo-drvobj.pFreeProc;if(pFreeProc){NT_VERIFY(pFreeProc(pedo-drvobj));// 调用驱动释放回调}}兜底清理即使驱动从未调用EngDeleteDriverObj对象最终被句柄表回收时也会调用pFreeProc避免资源泄漏。4. 生命周期与状态转换EngCreateDriverObj(GDI 句柄表分配, pvObj/pFreeProc/hdev/dhpdev)EngLockDriverObj(共享/排他锁)驱动访问 pvObj 私有数据EngUnlockDriverObjEngDeleteDriverObj(bCallBack)GDIOBJ_vDeleteObject(pFreeProc 已置 NULL, 不重复调用)句柄表回收(DRIVEROBJ_vCleanup → pFreeProc)已分配使用中删除中已删除兜底清理数据流图GDI 对象管理器显示驱动释放驱动资源驱动私有资源 pvObjEngCreateDriverObj(pvObj, pFreeProc, hdev)EngLockDriverObj /EngUnlockDriverObj(访问私有数据)EngDeleteDriverObj或依赖回收GDIOBJ_AllocObjWithHandleEDRIVEROBJ 句柄GDIOBJ_TryLockObject(GDIObjType_DRVOBJ_TYPE)GDIOBJ_vDeleteObjectDRIVEROBJ_vCleanup→ pFreeProc5. 设计特点总结驱动私有数据封装GDI 提供标准对象机制让驱动挂载私有数据pvObj与 GDI 对象管理器无缝集成。回调兜底清理DRIVEROBJ_vCleanup在对象回收时调用pFreeProc——即使驱动忘记删除资源也不泄漏。双释放保护EngDeleteDriverObj将pFreeProc置 NULL避免手动删除 对象回收双重释放。句柄安全全部通过HDRVOBJ句柄 GDIOBJ_TryLockObject访问杜绝野指针。锁计数校验EngUnlockDriverObj校验锁计数≥2防止不平衡解锁。设备关联自动填充dhpdev从hdevPDEVOBJ自动提取驱动无需重复提供。6. 源码索引位置关键内容[driverobj.h](file:///d:/reactos/win32ss/gdi/eng/driverobj.h#L4-L11)EDRIVEROBJ 结构[driverobj.h](file:///d:/reactos/win32ss/gdi/eng/driverobj.h#L17-L25)分配/解锁/锁定宏[driverobj.c](file:///d:/reactos/win32ss/gdi/eng/driverobj.c#L22-L34)DRIVEROBJ_vCleanup兜底清理[driverobj.c](file:///d:/reactos/win32ss/gdi/eng/driverobj.c#L38-L69)EngCreateDriverObj[driverobj.c](file:///d:/reactos/win32ss/gdi/eng/driverobj.c#L72-L109)EngDeleteDriverObj双释放保护[driverobj.c](file:///d:/reactos/win32ss/gdi/eng/driverobj.c#L112-L124)EngLockDriverObj[driverobj.c](file:///d:/reactos/win32ss/gdi/eng/driverobj.c#L127-L159)EngUnlockDriverObj锁计数校验[winddi.h](file:///d:/reactos/sdk/include/psdk/winddi.h#L408-L413)DRIVEROBJ DDI 公开结构关联模块[ntgdi/gdiobj.c](file:///d:/reactos/win32ss/gdi/ntgdi/gdiobj.c) / gdiobj.h — GDIOBJ_AllocObjWithHandle 等对象管理器[pdevobj.h](file:///d:/reactos/win32ss/gdi/eng/pdevobj.h) — hdev 类型PDEVOBJ关联文档《ReactOS 图形系统分析_4.md》— GDI 引擎整体架构本文件是对象管理子模块本文档基于 ReactOS 源代码win32ss/gdi/eng/driverobj.c、driverobj.h分析2026 年 8 月