MirrorDriver
A MirrorDriver with SharedMemory useing EngMapFile
Install / Use
/learn @Niap/MirrorDriverREADME
google关键字"MirrorDriver",大部分的可以看到一些应用层的代码,但是驱动层的代码寥寥无几,实际上只有MirrorDriver VNC和Qemu的显卡驱动有相关代码。但实际上从微软的Sample Code修改一下就可以很快实现一个自己的MirrorDriver
微软Sample Code 里面的MirrorDriver
MirrorDriver在xp时代是最有效的转屏方式,原理是直接从gdi桌面混合器中直接获取图像数据。那么如果获取图像数据又有两种方式吗,一种是使用文件,另外一种是客户端先分配一段内存然后通过驱动程序让MirrorDriver在这段内存中写入图像数据。
目录结构:微软的SampleCode在WDK7600的\src\video\displays\mirror位置,需要注意的是,MirrorDriver分成三个部分一个是MiniPort驱动,对应的是mini文件夹,作用是实现一个小端口驱动的基本雏形,可以理解为引导程序,其次是MirrorDriver的dll部分,这个具体实现了MirrorDriver框架的一些回调,是整个驱动中最重要的部分,app则是生成一个启动\停止MirrorDriver的控制台程序。
安装方法:可以分别在mini、disp、app目录分别执行bld命令,生成三个文件mirror.dll、mirror.sys,还需要再app目录下找到mirror.inf,讲这三个文件放在同一个文件夹中,右键点击mirror.info,选择安装即可。
修改Sample Code
1、在文件driver.h中添加
PVOID pvTmpBuffer; // ptr to MIRRSURF bits for screen surface
ULONG_PTR pMappedFile;
2、在DrvEnableSurface函数中 flHooks |= flGlobalHooks 后的代码替换成一下代码,实际上,EngCreateDeviceSurface和EngCreateBitmap从文档上看没有什么差别,都可以。
mirrorsize = (ULONG)(ppdev->cxScreen * ppdev->cyScreen * BitsPerPel);
ppdev->pvTmpBuffer = EngMapFile(L"\\??\\c:\\video.dat",
mirrorsize,
&ppdev->pMappedFile);
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);
}
return(hsurf);
3、参考源码,修改DrvCopyBits、DrvBitBlt、DrvTextOut等函数,直接调用底层Eng*函数,让驱动直接往下执行。 4、修改sreen.c文件,整体替换就行了。原理可能需要了解gdi内部绘图方式了。 5、编译安装重启后,驱动会在c盘下新建文件video.dat文件,文件内容就是桌面的镜像画面,实际上就是rgba数据
客户端实现
1、获取共享内存文件的内容的指针。
PCHAR VideoMemory_GetSharedMemory(void)
{
PCHAR pVideoMemory;
HANDLE hMapFile, hFile;
hFile = CreateFile("c:\\video.dat", 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 = (PCHAR) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
CloseHandle(hMapFile);
}
CloseHandle(hFile);
}
return pVideoMemory;
}
2、生成一张bitmap图片,生成文件头,bitmap头,然后把图像数据拼接在后面,这里可以参考《windows 程序设计》关于dib那章的内容。
void captureScreenFrame(int width,int height,RECT cropRegin, PCHAR myframebuffer,int index)
{
BITMAPINFOHEADER infoHeader;
BITMAPFILEHEADER fileHeader;
const int cropReginWidth = cropRegin.right -cropRegin.left;
const int cropReginHeight = cropRegin.bottom -cropRegin.top;
const int bits = 32;
const int bitPerPexcel = 4;
const int imageSize = width*height*bitPerPexcel;
const int headerSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biWidth = cropReginWidth ;
infoHeader.biHeight = cropReginHeight ;
infoHeader.biPlanes = 1 ;
infoHeader.biBitCount = (WORD) bits ;
infoHeader.biCompression = BI_RGB ;
infoHeader.biSizeImage = imageSize;
infoHeader.biXPelsPerMeter = 0 ;
infoHeader.biYPelsPerMeter = 0 ;
infoHeader.biClrUsed = (bits <= 8) ? 1<<bits : 0;
infoHeader.biClrImportant = 0 ;
//位图文件头结构
fileHeader.bfType=0x4D42;//set the attribute of BITMAPFILEHEADER
fileHeader.bfSize=headerSize+imageSize;
fileHeader.bfReserved1=0;
fileHeader.bfReserved2=0;
fileHeader.bfOffBits=headerSize;
PCHAR imageData = (PCHAR)malloc(imageSize);
cropWindow(imageData,myframebuffer,width,height,cropRegin);
//memcpy(lpBits, myframebuffer, width*height*4);
CHAR fileName[20];
sprintf(fileName,"c://caps//%d.bmp",index);
HANDLE pFile = CreateFile(fileName,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
ULONG written;
WriteFile(pFile,&fileHeader,sizeof(BITMAPFILEHEADER),&written,NULL);
WriteFile(pFile,&infoHeader,sizeof(BITMAPINFOHEADER),&written,NULL);
WriteFile(pFile,imageData,imageSize,&written,NULL);
CloseHandle(pFile);
free(imageData);
}
Related Skills
node-connect
343.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
92.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.3kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
