ReactOS 图形系统分析(13):驱动对象 --- DRIVEROBJ
1. 概述
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 DRIVEROBJ(DDK 公开结构,winddi.h(file:///d:/reactos/sdk/include/psdk/winddi.h#L408-L413))
c
typedef struct _DRIVEROBJ {
PVOID pvObj; // 驱动私有数据指针
FREEOBJPROC pFreeProc; // 释放回调(对象删除时调用)
HDEV hdev; // 关联的引擎设备句柄(PDEVOBJ)
DHPDEV dhpdev; // 驱动设备句柄
} DRIVEROBJ;
FREEOBJPROC 回调原型:
c
typedef BOOL (*FREEOBJPROC)(DRIVEROBJ *pdo);
驱动在回调中释放 pvObj 指向的资源,返回 TRUE 表示成功。
2.2 EDRIVEROBJ(引擎内部扩展,driverobj.h(file:///d:/reactos/win32ss/gdi/eng/driverobj.h#L4-L11))
c
typedef struct _EDRIVEROBJ
{
BASEOBJECT baseobj; // GDI 对象头(句柄/锁/标志)
DRIVEROBJ drvobj; // DDI 公开部分
PVOID reserved; // 保留
} EDRIVEROBJ, *PEDRIVEROBJ;
2.3 分配/锁定宏
c
/* 从 GDI 句柄表分配(类型 GDI_OBJECT_TYPE_DRIVEROBJ / GDIObjType_DRVOBJ_TYPE) */
#define DRIVEROBJ_AllocObjectWithHandle() \
((PEDRIVEROBJ)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DRIVEROBJ, sizeof(EDRIVEROBJ)))
#define DRIVEROBJ_UnlockObject(pdo) GDIOBJ_vUnlockObject((POBJ)pdo)
/* 尝试锁定(返回 NULL 表示对象不存在/被独占) */
FORCEINLINE PEDRIVEROBJ DRIVEROBJ_TryLockObject(HDRVOBJ hdo)
{
return (PEDRIVEROBJ)GDIOBJ_TryLockObject(hdo, GDIObjType_DRVOBJ_TYPE);
}
3. 核心函数分析
3.1 创建 --- EngCreateDriverObj
c
HDRVOBJ APIENTRY EngCreateDriverObj(PVOID pvObj, FREEOBJPROC pFreeObjProc, HDEV hdev)
{
PDEVOBJ *ppdev = (PDEVOBJ*)hdev;
/* 1. 从 GDI 句柄表分配 EDRIVEROBJ */
pedo = DRIVEROBJ_AllocObjectWithHandle();
if (!pedo) return NULL;
hdo = pedo->baseobj.hHmgr; // 句柄
/* 2. 填充字段 */
pedo->drvobj.pvObj = pvObj; // 驱动私有数据
pedo->drvobj.pFreeProc = pFreeObjProc; // 释放回调
pedo->drvobj.hdev = hdev; // 设备句柄(PDEVOBJ 指针)
pedo->drvobj.dhpdev = ppdev->dhpdev; // 从 PDEV 取驱动设备句柄
/* 3. 解锁并返回句柄 */
DRIVEROBJ_UnlockObject(pedo);
return hdo;
}
要点: hdev 参数实际是 PDEVOBJ 指针(HDEV 类型),从中直接取 dhpdev 填入------驱动无需自己传。
3.2 删除 --- EngDeleteDriverObj
c
BOOL APIENTRY EngDeleteDriverObj(HDRVOBJ hdo, BOOL bCallBack, BOOL bLocked)
{
/* 1. 锁定对象获取指针 */
pedo = DRIVEROBJ_TryLockObject(hdo);
if (!pedo) return FALSE;
/* 2. bCallBack=TRUE 时手动调用释放回调 */
if (bCallBack)
{
if (!pedo->drvobj.pFreeProc(&pedo->drvobj)) // 回调失败则中止
{
DRIVEROBJ_UnlockObject(pedo);
return FALSE;
}
}
/* 3. 清空回调,防止对象回收时再次调用(双释放保护) */
pedo->drvobj.pFreeProc = NULL;
/* 4. bLocked=TRUE 时调用者已持锁,需额外解锁 */
if (bLocked)
DRIVEROBJ_UnlockObject(pedo);
/* 5. 删除对象(此后对象回收不会再调 pFreeProc) */
GDIOBJ_vDeleteObject(&pedo->baseobj);
return TRUE;
}
双释放保护: 删除时先把 pFreeProc 置 NULL,这样即使 bCallBack=FALSE(未调用回调),对象回收阶段 DRIVEROBJ_vCleanup 也不会重复调用。
3.3 锁定 --- EngLockDriverObj / EngUnlockDriverObj
c
PDRIVEROBJ APIENTRY EngLockDriverObj(HDRVOBJ hdo)
{
pedo = DRIVEROBJ_TryLockObject(hdo);
return pedo ? &pedo->drvobj : NULL; // 返回 DDI 公开部分
}
BOOL APIENTRY EngUnlockDriverObj(HDRVOBJ hdo)
{
/* 先锁定取得 cExclusiveLock 计数 */
pedo = DRIVEROBJ_TryLockObject(hdo);
cLocks = pedo->baseobj.cExclusiveLock;
DRIVEROBJ_UnlockObject(pedo);
/* 若之前未持锁(计数 < 2),解锁不匹配则失败 */
if (cLocks < 2)
return FALSE;
DRIVEROBJ_UnlockObject(pedo); // 第二次解锁
return TRUE;
}
要点: 锁计数实现------EngLockDriverObj 加 1 次锁,EngUnlockDriverObj 需要对象已被锁(计数 ≥ 2,即已锁 + 本次临时锁)才允许解锁,防止不平衡的解锁。
3.4 清理回调 --- DRIVEROBJ_vCleanup
对象被 GDI 对象管理器回收时调用:
c
VOID NTAPI DRIVEROBJ_vCleanup(PVOID pObject)
{
PEDRIVEROBJ pedo = pObject;
pFreeProc = pedo->drvobj.pFreeProc;
if (pFreeProc)
{
NT_VERIFY(pFreeProc(&pedo->drvobj)); // 调用驱动释放回调
}
}
兜底清理: 即使驱动从未调用 EngDeleteDriverObj,对象最终被句柄表回收时也会调用 pFreeProc,避免资源泄漏。
4. 生命周期与状态转换
#mermaid-svg-j6tcZimksYJ2LBUr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-j6tcZimksYJ2LBUr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-j6tcZimksYJ2LBUr .error-icon{fill:#552222;}#mermaid-svg-j6tcZimksYJ2LBUr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-j6tcZimksYJ2LBUr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-j6tcZimksYJ2LBUr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr .marker.cross{stroke:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-j6tcZimksYJ2LBUr p{margin:0;}#mermaid-svg-j6tcZimksYJ2LBUr defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-j6tcZimksYJ2LBUr g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-j6tcZimksYJ2LBUr g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-j6tcZimksYJ2LBUr g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-j6tcZimksYJ2LBUr g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-j6tcZimksYJ2LBUr .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-j6tcZimksYJ2LBUr .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-j6tcZimksYJ2LBUr .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-j6tcZimksYJ2LBUr .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-j6tcZimksYJ2LBUr .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-j6tcZimksYJ2LBUr .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-j6tcZimksYJ2LBUr .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-j6tcZimksYJ2LBUr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j6tcZimksYJ2LBUr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-j6tcZimksYJ2LBUr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j6tcZimksYJ2LBUr .edgeLabel .label text{fill:#333;}#mermaid-svg-j6tcZimksYJ2LBUr .label div .edgeLabel{color:#333;}#mermaid-svg-j6tcZimksYJ2LBUr .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-j6tcZimksYJ2LBUr .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-j6tcZimksYJ2LBUr .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-j6tcZimksYJ2LBUr .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j6tcZimksYJ2LBUr .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j6tcZimksYJ2LBUr #statediagram-barbEnd{fill:#333333;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j6tcZimksYJ2LBUr .cluster-label,#mermaid-svg-j6tcZimksYJ2LBUr .nodeLabel{color:#131300;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-j6tcZimksYJ2LBUr .note-edge{stroke-dasharray:5;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-note text{fill:black;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram-note .nodeLabel{color:black;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagram .edgeLabel{color:red;}#mermaid-svg-j6tcZimksYJ2LBUr #dependencyStart,#mermaid-svg-j6tcZimksYJ2LBUr #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-j6tcZimksYJ2LBUr .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-j6tcZimksYJ2LBUr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} EngCreateDriverObj
(GDI 句柄表分配, pvObj/pFreeProc/hdev/dhpdev)
EngLockDriverObj
(共享/排他锁)
驱动访问 pvObj 私有数据
EngUnlockDriverObj
EngDeleteDriverObj(bCallBack)
GDIOBJ_vDeleteObject
(pFreeProc 已置 NULL, 不重复调用)
句柄表回收
(DRIVEROBJ_vCleanup → pFreeProc)
已分配
使用中
删除中
已删除
兜底清理
数据流图:
#mermaid-svg-7BVWvCI6bOQ97Bd1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .error-icon{fill:#552222;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .marker.cross{stroke:#333333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 p{margin:0;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster-label text{fill:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster-label span{color:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster-label span p{background-color:transparent;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .label text,#mermaid-svg-7BVWvCI6bOQ97Bd1 span{fill:#333;color:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .node rect,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node circle,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node ellipse,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node polygon,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .rough-node .label text,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node .label text,#mermaid-svg-7BVWvCI6bOQ97Bd1 .image-shape .label,#mermaid-svg-7BVWvCI6bOQ97Bd1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .rough-node .label,#mermaid-svg-7BVWvCI6bOQ97Bd1 .node .label,#mermaid-svg-7BVWvCI6bOQ97Bd1 .image-shape .label,#mermaid-svg-7BVWvCI6bOQ97Bd1 .icon-shape .label{text-align:center;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .node.clickable{cursor:pointer;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .arrowheadPath{fill:#333333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7BVWvCI6bOQ97Bd1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7BVWvCI6bOQ97Bd1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster text{fill:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .cluster span{color:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7BVWvCI6bOQ97Bd1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .icon-shape,#mermaid-svg-7BVWvCI6bOQ97Bd1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .icon-shape p,#mermaid-svg-7BVWvCI6bOQ97Bd1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .icon-shape .label rect,#mermaid-svg-7BVWvCI6bOQ97Bd1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7BVWvCI6bOQ97Bd1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7BVWvCI6bOQ97Bd1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7BVWvCI6bOQ97Bd1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} GDI 对象管理器
显示驱动
释放驱动资源
驱动私有资源 pvObj
EngCreateDriverObj
(pvObj, pFreeProc, hdev)
EngLockDriverObj /
EngUnlockDriverObj
(访问私有数据)
EngDeleteDriverObj
或依赖回收
GDIOBJ_AllocObjWithHandle
EDRIVEROBJ + 句柄
GDIOBJ_TryLockObject
(GDIObjType_DRVOBJ_TYPE)
GDIOBJ_vDeleteObject
DRIVEROBJ_vCleanup
→ pFreeProc
5. 设计特点总结
- 驱动私有数据封装 :GDI 提供标准对象机制让驱动挂载私有数据(
pvObj),与 GDI 对象管理器无缝集成。 - 回调兜底清理 :
DRIVEROBJ_vCleanup在对象回收时调用pFreeProc------即使驱动忘记删除,资源也不泄漏。 - 双释放保护 :
EngDeleteDriverObj将pFreeProc置 NULL,避免"手动删除 + 对象回收"双重释放。 - 句柄安全 :全部通过
HDRVOBJ句柄 +GDIOBJ_TryLockObject访问,杜绝野指针。 - 锁计数校验 :
EngUnlockDriverObj校验锁计数(≥2)防止不平衡解锁。 - 设备关联自动填充 :
dhpdev从hdev(PDEVOBJ)自动提取,驱动无需重复提供。
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 月)