VC Mirror Driver显示虚拟驱动经典开发
一个简单的显示驱动实例
windows wdk 7600的 mirror(镜像) 显示驱动部分
基本流程:
Windows 2000 DDK包含了一个例子镜像驱动程序,在 上面3个目录中包括了组件源文件。
目录
包含的源文件
Video\displays\mirror\dll
镜像驱动程序
Video\miniport\mirror
微端口驱动程序
Video\displays\mirror\app
用户模式服务。也包含mirror.inf。
打开disp文件夹 C:\WinDDK\7600.16385.1\src\video\displays\mirror\disp// wdk 2000 要方便一些
修改sources文件 // 指定警告错误级别
MSC_WARNING_LEVEL=/W4 改为:MSC_WARNING_LEVEL=/W3
打开debug.c 日志打印级别为 ULONG DebugLevel = 4
一.在driver.h头文件中:
1.pdev结构体添加缓存区指针
typedef struct _PDEV
{
HANDLE hDriver; // Handle to \Device\Screen
HDEV hdevEng; // Engine's handle to PDEV
HSURF hsurfEng; // Engine's handle to surface
HPALETTE hpalDefault; // Handle to the default palette for device.
PBYTE pjScreen; // This is pointer to base screen address
ULONG cxScreen; // Visible screen width
ULONG cyScreen; // Visible screen height
POINTL ptlOrg; // Where this display is anchored in
// the virtual desktop.
ULONG ulMode; // Mode the mini-port driver is in.
LONG lDeltaScreen; // Distance from one scan to the next.
ULONG cScreenSize; // size of video memory, including
// offscreen memory.
PVOID pOffscreenList; // linked list of DCI offscreen surfaces.
FLONG flRed; // For bitfields device, Red Mask
FLONG flGreen; // For bitfields device, Green Mask
FLONG flBlue; // For bitfields device, Blue Mask
ULONG cPaletteShift; // number of bits the 8-8-8 palette must
// be shifted by to fit in the hardware
// palette.
ULONG ulBitCount; // # of bits per pel 8,16,24,32 are only supported.
POINTL ptlHotSpot; // adjustment for pointer hot spot
VIDEO_POINTER_CAPABILITIES PointerCapabilities; // HW pointer abilities
PVIDEO_POINTER_ATTRIBUTES pPointerAttributes; // hardware pointer attributes
DWORD cjPointerAttributes; // Size of buffer allocated
BOOL fHwCursorActive; // Are we currently using the hw cursor
PALETTEENTRY *pPal; // If this is pal managed, this is the pal
BOOL bSupportDCI; // Does the miniport support DCI?
PVOID pvTmpBuffer; // ptr to MIRRSURF bits for screen surface
/* Add a file buffer memory pointer */
//==================================
PVOID pVideoMemory;
ULONG_PTR hMem;
//==================================
} PDEV, *PPDEV;
2.创建缓存区. 在函数中DrvEnableSurface绘画 // 提供一个绘画表面
HSURF DrvEnableSurface(
DHPDEV dhpdev)
{
PPDEV ppdev;
HSURF hsurf;
SIZEL sizl;
ULONG ulBitmapType;
FLONG flHooks;
ULONG mirrorsize;
ULONG BitsPerPel;
MIRRSURF *mirrsurf;
DHSURF dhsurf;
// Create engine bitmap around frame buffer.
DISPDBG((0,"DrvEnableSurface:\n"));
ppdev = (PPDEV) dhpdev;
ppdev->ptlOrg.x = 0;
ppdev->ptlOrg.y = 0;
sizl.cx = ppdev->cxScreen;
sizl.cy = ppdev->cyScreen;
if (ppdev->ulBitCount == 16)
{
ulBitmapType = BMF_16BPP;
flHooks = HOOKS_BMF16BPP;
BitsPerPel = 2;
}
else if (ppdev->ulBitCount == 24)
{
ulBitmapType = BMF_24BPP;
flHooks = HOOKS_BMF24BPP;
BitsPerPel = 3;
}
else
{
ulBitmapType = BMF_32BPP;
flHooks = HOOKS_BMF32BPP;
BitsPerPel = 4;
}
flHooks |= flGlobalHooks;
mirrorsize = (ULONG)(ppdev->cxScreen * ppdev->cyScreen * BitsPerPel);
ppdev->pvTmpBuffer = EngMapFile( // Mapping file buffer memory to disk
L"\\??\\c:\\video.dat",
mirrorsize,
&ppdev->hMem);
hsurf = (HSURF) EngCreateBitmap(sizl,
ppdev->lDeltaScreen,
ulBitmapType,
0,
(PVOID)(ppdev->pvTmpBuffer));
if (hsurf == (HSURF) 0)
{
RIP("DISP DrvEnableSurface failed EngCreateBitmap\n");
return(FALSE);
}
if (!EngAssociateSurface(hsurf, ppdev->hdevEng, flHooks))
{
RIP("DISRP DrvEnableSurface failed EngAssociateSurface\n");
EngDeleteSurface(hsurf);
return(FALSE);
}
ppdev->hsurfEng = (HSURF) hsurf;
return(hsurf);
}
3.在函数中DrvDisableSurface // 清理表面
VOID DrvDisableSurface(
DHPDEV dhpdev)
{
PPDEV ppdev = (PPDEV) dhpdev;
DISPDBG((0,"DrvDisableSurface:\n"));
EngDeleteSurface( ppdev->hsurfEng );
}
4. 在函数中DrvDisablePDEV // 退出时要删的缓存区
VOID DrvDisablePDEV(
DHPDEV dhpdev)
{
PPDEV ppdev = (PPDEV) dhpdev;
EngDeletePalette(ppdev->hpalDefault);
EngFreeMem(dhpdev);
EngUnmapFile(ppdev->hMem);
EngDeleteFile(L"\\??\\c:\\video.dat");
}
5.修正调色板
打开screen.c 修改调色板 颜色为 R G B
BOOL bInitPDEV(
PPDEV ppdev,
DEVMODEW *pDevMode,
GDIINFO *pGdiInfo,
DEVINFO *pDevInfo)
{
ULONG red, green, blue;
INT i;
//
// Fill in the GDIINFO data structure with the information returned from
// the kernel driver.
//
ppdev->ulMode = 0;
ppdev->cxScreen = pDevMode->dmPelsWidth;
ppdev->cyScreen = pDevMode->dmPelsHeight;
ppdev->ulBitCount = pDevMode->dmBitsPerPel;
ppdev->lDeltaScreen = 0;
ppdev->flRed = 0x00FF0000;
ppdev->flGreen = 0x000FF00;
ppdev->flBlue = 0x00000FF;
......
*pDevInfo = gDevInfoFrameBuffer;
if (ppdev->ulBitCount == 16)
{
pDevInfo->iDitherFormat = BMF_16BPP;
// each word single pixel 5-5-5
pDevInfo->hpalDefault = ppdev->hpalDefault =
EngCreatePalette(PAL_BITFIELDS, 0,NULL,
0x7c00,0x03e0,0x001f);
}
else
{
if (ppdev->ulBitCount == 24)
{
pDevInfo->iDitherFormat = BMF_24BPP;
}
else
{
pDevInfo->iDitherFormat = BMF_32BPP;
}
pDevInfo->hpalDefault = ppdev->hpalDefault =
EngCreatePalette(PAL_BITFIELDS, 0,NULL,
ppdev->flRed,ppdev->flGreen,ppdev->flBlue);
}
return(TRUE);
}
6.根据Hook标志路径回调GDI图形引擎管理
如:<BitBlt>
BOOL DrvBitBlt(
IN SURFOBJ *psoDst,
IN SURFOBJ *psoSrc,
IN SURFOBJ *psoMask,
IN CLIPOBJ *pco,
IN XLATEOBJ *pxlo,
IN RECTL *prclDst,
IN POINTL *pptlSrc,
IN POINTL *pptlMask,
IN BRUSHOBJ *pbo,
IN POINTL *pptlBrush,
IN ROP4 rop4
)
{
DISPDBG((0,"DrvBitBlt:(%d,%d,%d,%d)\n", prclDst->bottom, prclDst->left,prclDst->right, prclDst->top));
return EngBitBlt(psoDst, psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc, pptlMask, pbo, pptlBrush, rop4);
//return TRUE;
}
7.变化的矩形
由源表面到目标表面都会有相对的变化矩形
例:通过debug打印
DISPDBG((0,"DrvBitBlt:(%d,%d,%d,%d)\n", prclDst->bottom, prclDst->left,prclDst->right, prclDst->top));
应用程序的使用
文件内存映射
将建立的c:\\video.dat文件进行映射
CString ptr = L"C:\\video.dat";
hFile = CreateFile(ptr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if(hFile && hFile != INVALID_HANDLE_VALUE)
{
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if(hMapFile && hMapFile != INVALID_HANDLE_VALUE)
{
pVideoMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
CloseHandle(hMapFile);
}
CloseHandle(hFile);
}
pVideoMemeory为变化数据指针。
微端口(miniport):
镜像驱动程序在微端口驱动程序中的功能需求很小,从代码上可以比较出镱像驱动少了许多功能,唯一必须实现的函数是DriverEntry,它是由微端口驱动程序导出的,也可以由以下函数导出:
HwVidFindAdapter
HwVidInitialize
HwVidStartIo
既然没有物理的显示设备与一个镜像的表面相关联,这三个函数可以空执行并且总是返回成功。
使用net内核api头文件冲突问题:
net内核api在wdk 7600上使用时需要自建立一个头文件及源文件(如 :xxx1.c与xxx1.h),将(如:#include "xxx1.h")导入mirror.c的源文件中。
如:在微端口上使用api来映射内存,跟据系统环境配置相应的net内核api来实现。
这是一个入门例子用来了解体会windows图形显示驱动的一些windows图形体系结构等。
需要参照的代码示例。
XP SP3测试
————————————————
版权声明:本文为CSDN博主「qwer430401」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qwer430401/article/details/53047022