;goto make ;直接将显存数据保存为BMP图片,注意:是实验代码! .386 ;注意:保存后的BMP图片是垂直倒了90度.不知道怎么弄哈~ .model flat, stdcall;显卡物理地址可以用PCI配置空间获取,这里实验从设备管理器中获取的. option casemap:none ;作者:成松林 QQ:179641795 Email:cheng_5103@126.com ;转贴请保留作者信息,文章发篇不容易!请大家尊重下吧!!!!! include d:\masm32\include\w2k\ntstatus.inc include d:\masm32\include\w2k\hal.inc include d:\masm32\include\w2k\ntddk.inc include d:\masm32\include\w2k\win32k.inc include d:\masm32\include\w2k\ntoskrnl.inc includelib d:\masm32\lib\w2k\ntoskrnl.lib includelib d:\masm32\lib\w2k\hal.lib includelib d:\masm32\lib\w2k\win32k.lib include d:\masm32\Macros\Strings.mac .const CCOUNTED_UNICODE_STRING "\\??\\C:\\aa.bmp",uFile_Name,4 ;将显存数据写入文件 .data bmphd db 42h,4dh,36h,00h,24h,0,0000,000,0,0,036h,000,000,00,28h,0 db 000,000,000,04h,000,0,0000,003,0,0,0001,000,18h,00,000,0 db 000,000,000,00h,24h,0,0c4h,0eh,0,0,0c4h,0eh,000,00,000,0 db 000,000,000,000,000,0,0000 DataSize dd 1024*768*4 ;注意:显存屏幕数据大小,显示色彩为32位色! BmpSize dd 0 File_Handle dd 0 ScrnBuffer dd 0 ScrnPhysicalAddress dd 0f0000000h ;显存物理地地址,可用PCI配置空间端口CF8、CFC获取. ScrnSizeMemory dd 1280*1024*4 ;显存大小,可在PCI空间获取.这里用支持的最大分辨率. DisplayLineAddr dd 0 ;调用MmMapIoSpace函数映射的虚拟地址. DisplayMDLAddr dd 0 OB_AB OBJECT_ATTRIBUTES <> Status IO_STATUS_BLOCK <> ByteOffset LARGE_INTEGER<> .code ;**************************************************************************************************************** DriverEntry proc uses ebx ecx edx esi edi pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING invoke MmMapIoSpace,ScrnPhysicalAddress,0,ScrnSizeMemory,FALSE ;建立显存物理地址到线性地址映射 mov DisplayLineAddr,eax ;保存线性地址 invoke IoAllocateMdl,DisplayLineAddr,ScrnSizeMemory,FALSE,FALSE,NULL;分配显存MDL描述,以便锁定 .if eax == 0 ;注意:发现分配太大的内存会失败! invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory ;释放显存映射资源 ret .endif mov DisplayMDLAddr,eax ;保存分配的显存MDL描述 invoke MmProbeAndLockPages,DisplayMDLAddr,KernelMode,IoReadAccess OR IoWriteAccess;锁存内存操作 invoke ExAllocatePool,PagedPool,DataSize ;分配内存缓冲,拷贝显存数据 .if eax == 0 ;分配失败 invoke MmUnlockPages,DisplayMDLAddr ;解出显存锁定 invoke IoFreeMdl,DisplayMDLAddr ;释放分配的显存MDL描述 invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory ;释放显存映射资源 ret .endif mov ScrnBuffer,eax ;保存分配的内存缓冲 mov edi,ScrnBuffer mov esi,DisplayLineAddr ;esi->显存线性地址(手动获取的仅为实验) mov ecx,DisplayLineAddr add ecx,DataSize .while esi < ecx ;拷贝显存数据到本地 mov eax,[esi] mov [edi],eax add edi,3 ;BMP数据每个象素点=32位色下显存4个字节的最后一个字节去掉. add esi,4 .endw invoke MmUnlockPages,DisplayMDLAddr ;解出显存MDL描述锁定 invoke IoFreeMdl,DisplayMDLAddr ;释放分配的显存MDL描述 invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory ;释放显存映射资源 InitializeObjectAttributes addr OB_AB,addr uFile_Name,OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE,NULL,NULL;宏native.inc:InitializeObjectAttributes invoke ZwCreateFile,addr File_Handle,GENERIC_WRITE,addr OB_AB,addr Status,NULL,FILE_ATTRIBUTE_NORMAL,0,FILE_OVERWRITE_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0 .if eax !=0 ;建立打开文件失败 ret .endif mov ByteOffset.HighPart,0 mov ByteOffset.LowPart,0 invoke ZwWriteFile,File_Handle,NULL,NULL,NULL,addr Status,addr bmphd,36h,NULL,NULL mov ByteOffset.LowPart,36h mov esi,DataSize ;每个象素点占4个字节,最后一个字节0,bmp不保存的. shr esi,2 ;esi=有多少个象素 mov edi,DataSize sub edi,esi ;edi=BMP应该保存的字节数 mov BmpSize,edi invoke ZwWriteFile,File_Handle,NULL,NULL,NULL,addr Status,ScrnBuffer,BmpSize,addr ByteOffset,NULL invoke ZwClose,File_Handle invoke ExFreePool,ScrnBuffer ;释放分分配的保存显存数据的缓冲区 mov eax, 0 ret DriverEntry endp end DriverEntry :make set drv=DRRamScreen ..\bin\ml /nologo /c /coff %drv%.bat ..\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj del %drv%.obj pause