ReactOS 图形系统分析(13):驱动对象 — DRIVEROBJ

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. 设计特点总结

  1. 驱动私有数据封装 :GDI 提供标准对象机制让驱动挂载私有数据(pvObj),与 GDI 对象管理器无缝集成。
  2. 回调兜底清理DRIVEROBJ_vCleanup 在对象回收时调用 pFreeProc------即使驱动忘记删除,资源也不泄漏。
  3. 双释放保护EngDeleteDriverObjpFreeProc 置 NULL,避免"手动删除 + 对象回收"双重释放。
  4. 句柄安全 :全部通过 HDRVOBJ 句柄 + GDIOBJ_TryLockObject 访问,杜绝野指针。
  5. 锁计数校验EngUnlockDriverObj 校验锁计数(≥2)防止不平衡解锁。
  6. 设备关联自动填充dhpdevhdev(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.cdriverobj.h 分析(2026 年 8 月)

相关推荐
ZJU_统一阿萨姆4 小时前
【推理优化】KV Cache 量化:在不牺牲质量的前提下压榨更多内存
人工智能·语言模型·系统架构·vllm
Dr.kangder17 小时前
嵌入式面试总结(十五)——异常处理
单片机·面试·职场和发展·系统架构·嵌入式
caimouse1 天前
ReactOS 图形系统分析(1):VBE MiniPort 驱动 vgapnp.sys
系统架构
ZJU_统一阿萨姆1 天前
【推理优化】连续批处理:当推理吞吐量遇到天花板
人工智能·语言模型·系统架构
caimouse1 天前
ReactOS 图形系统分析(4):GDI 引擎 (eng)
系统架构
caimouse1 天前
ReactOS 图形系统分析(9):物理设备对象 — PDEVOBJ
系统架构
caimouse1 天前
ReactOS 图形系统分析(11):映射设备对象 — MDEVOBJ(多显示器)
系统架构·计算机外设
国科安芯2 天前
详解ADC 规则组外部触发:CH2、CH3 与 TRGO2
运维·网络·单片机·嵌入式硬件·mcu·系统架构
Dr.kangder2 天前
嵌入式面试总结(十)——流水线
单片机·嵌入式硬件·面试·职场和发展·系统架构·嵌入式