之前整理过一篇《WinCE6.0中应用程序如何直接访问物理空间》的短文,文中介绍的方法突破了WinCE6.0系统本身的限制,使应用程序能够直接读写指定的内存地址,如访问系统显存。在WinCE中,使用托管代码编写应用程序直接访问物理空间,之前也曾简单介绍过,当时是基于VB.NET实现的,请参考《WinCE下VB.NET程序的开发》。今天再凑一篇基于C#的。
原理之前两篇都已经讲过了,这里不再赘述。实现方法与VB.NET类似,首先用C++编写一个动态链接库,实现所需功能,并导出相应的函数。在托管代码中调用这些函数读写指定的物理空间。闲话不再多说,直接附上参考代码。
SysApi.h代码如下:
1
#ifndef __SYSAPI_H__
2 #define __SYSAPI_H__
3
4 #ifdef __cplusplus
5 extern " C " {
6 #endif
7
8 #ifdef _WINDLL
9 #ifdef SYSAPI_EXPORTS
10 #define CLASS_DECLSPEC __declspec (dllexport)
11 #else
12 #define CLASS_DECLSPEC __declspec (dllimport)
13 #endif
14 #else
15 #define CLASS_DECLSPEC
16 #endif
17
18 typedef struct {
19 void * pvDestMem;
20 DWORD dwPhysAddr;
21 DWORD dwSize;
22 } VIRTUAL_COPY_EX_DATA, * PVIRTUAL_COPY_EX_DATA;
23
24 #define IOCTL_VIRTUAL_COPY_EX CTL_CODE (FILE_DEVICE_UNKNOWN,3333,METHOD_BUFFERED,FILE_ANY_ACCESS)
25
26 CLASS_DECLSPEC LPVOID GetVirtual(DWORD dwPhyBaseAddress, DWORD dwSize);
27 CLASS_DECLSPEC VOID FreeVirtual(LPVOID pVirtualAddress);
28 CLASS_DECLSPEC VOID SetVirtual(LPVOID pVirtualAddress, BYTE val, DWORD dwSize);
29
30 #ifdef __cplusplus
31 }
32 #endif
33
34 #endif
2 #define __SYSAPI_H__
3
4 #ifdef __cplusplus
5 extern " C " {
6 #endif
7
8 #ifdef _WINDLL
9 #ifdef SYSAPI_EXPORTS
10 #define CLASS_DECLSPEC __declspec (dllexport)
11 #else
12 #define CLASS_DECLSPEC __declspec (dllimport)
13 #endif
14 #else
15 #define CLASS_DECLSPEC
16 #endif
17
18 typedef struct {
19 void * pvDestMem;
20 DWORD dwPhysAddr;
21 DWORD dwSize;
22 } VIRTUAL_COPY_EX_DATA, * PVIRTUAL_COPY_EX_DATA;
23
24 #define IOCTL_VIRTUAL_COPY_EX CTL_CODE (FILE_DEVICE_UNKNOWN,3333,METHOD_BUFFERED,FILE_ANY_ACCESS)
25
26 CLASS_DECLSPEC LPVOID GetVirtual(DWORD dwPhyBaseAddress, DWORD dwSize);
27 CLASS_DECLSPEC VOID FreeVirtual(LPVOID pVirtualAddress);
28 CLASS_DECLSPEC VOID SetVirtual(LPVOID pVirtualAddress, BYTE val, DWORD dwSize);
29
30 #ifdef __cplusplus
31 }
32 #endif
33
34 #endif
SysApi.cpp代码如下:
1
//
SysApi.cpp : 定义 DLL 应用程序的入口点。
2 //
3
4 #include " stdafx.h "
5 #include < windows.h >
6 #include < commctrl.h >
7 #include < Pkfuncs.h >
8 #include " SysApi.h "
9
10 BOOL APIENTRY DllMain( HANDLE hModule,
11 DWORD ul_reason_for_call,
12 LPVOID lpReserved
13 )
14 {
15 return TRUE;
16 }
17
18 CLASS_DECLSPEC LPVOID GetVirtual(DWORD dwPhyBaseAddress, DWORD dwSize)
19 {
20 volatile LPVOID pVirtual;
21 VIRTUAL_COPY_EX_DATA vced;
22
23 if (dwPhyBaseAddress & 0xFFF )
24 {
25 return NULL;
26 }
27
28 vced.dwPhysAddr = dwPhyBaseAddress >> 8 ;
29 pVirtual = VirtualAlloc( 0 , dwSize, MEM_RESERVE, PAGE_NOACCESS);
30 vced.pvDestMem = pVirtual;
31 vced.dwSize = dwSize;
32 KernelIoControl(IOCTL_VIRTUAL_COPY_EX, & vced, sizeof (vced), NULL, NULL, NULL);
33
34 return pVirtual;
35 }
36
37 CLASS_DECLSPEC VOID FreeVirtual(LPVOID pVirtualAddress)
38 {
39 VirtualFree(pVirtualAddress, 0 , MEM_RELEASE);
40 }
41
42 CLASS_DECLSPEC VOID SetVirtual(LPVOID pVirtualAddress, BYTE val, DWORD dwSize)
43 {
44 if (pVirtualAddress)
45 {
46 memset(pVirtualAddress, val, dwSize);
47 }
48 }
2 //
3
4 #include " stdafx.h "
5 #include < windows.h >
6 #include < commctrl.h >
7 #include < Pkfuncs.h >
8 #include " SysApi.h "
9
10 BOOL APIENTRY DllMain( HANDLE hModule,
11 DWORD ul_reason_for_call,
12 LPVOID lpReserved
13 )
14 {
15 return TRUE;
16 }
17
18 CLASS_DECLSPEC LPVOID GetVirtual(DWORD dwPhyBaseAddress, DWORD dwSize)
19 {
20 volatile LPVOID pVirtual;
21 VIRTUAL_COPY_EX_DATA vced;
22
23 if (dwPhyBaseAddress & 0xFFF )
24 {
25 return NULL;
26 }
27
28 vced.dwPhysAddr = dwPhyBaseAddress >> 8 ;
29 pVirtual = VirtualAlloc( 0 , dwSize, MEM_RESERVE, PAGE_NOACCESS);
30 vced.pvDestMem = pVirtual;
31 vced.dwSize = dwSize;
32 KernelIoControl(IOCTL_VIRTUAL_COPY_EX, & vced, sizeof (vced), NULL, NULL, NULL);
33
34 return pVirtual;
35 }
36
37 CLASS_DECLSPEC VOID FreeVirtual(LPVOID pVirtualAddress)
38 {
39 VirtualFree(pVirtualAddress, 0 , MEM_RELEASE);
40 }
41
42 CLASS_DECLSPEC VOID SetVirtual(LPVOID pVirtualAddress, BYTE val, DWORD dwSize)
43 {
44 if (pVirtualAddress)
45 {
46 memset(pVirtualAddress, val, dwSize);
47 }
48 }
C#的参考代码如下:
1
using
System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Text;
7 using System.Windows.Forms;
8 using System.Runtime.InteropServices;
9
10 namespace SysApp2
11 {
12 public partial class Form1 : Form
13 {
14 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
15 public static extern IntPtr GetVirtual( uint PhyBaseAddress, uint Size);
16 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
17 public static extern void FreeVirtual(IntPtr pVirtualAddress);
18 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
19 public static extern void SetVirtual(IntPtr pVirtualAddress, byte val, uint dwSize);
20
21 private IntPtr pLCDBuf;
22
23 public Form1()
24 {
25 InitializeComponent();
26 }
27
28 private void Black_Click( object sender, EventArgs e)
29 {
30 SetVirtual(pLCDBuf, 0x00 , 0x300000 );
31 }
32
33 private void White_Click( object sender, EventArgs e)
34 {
35 SetVirtual(pLCDBuf, 0xFF , 0x300000 );
36 }
37
38 private void FormClosed( object sender, EventArgs e)
39 {
40 FreeVirtual(pLCDBuf);
41 }
42
43 private void FormLoad( object sender, EventArgs e)
44 {
45 pLCDBuf = GetVirtual( 0x4C800000 , 0x300000 );
46 }
47 }
48 }
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Text;
7 using System.Windows.Forms;
8 using System.Runtime.InteropServices;
9
10 namespace SysApp2
11 {
12 public partial class Form1 : Form
13 {
14 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
15 public static extern IntPtr GetVirtual( uint PhyBaseAddress, uint Size);
16 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
17 public static extern void FreeVirtual(IntPtr pVirtualAddress);
18 [DllImport( " SysApi.dll " , CharSet = CharSet.Auto)]
19 public static extern void SetVirtual(IntPtr pVirtualAddress, byte val, uint dwSize);
20
21 private IntPtr pLCDBuf;
22
23 public Form1()
24 {
25 InitializeComponent();
26 }
27
28 private void Black_Click( object sender, EventArgs e)
29 {
30 SetVirtual(pLCDBuf, 0x00 , 0x300000 );
31 }
32
33 private void White_Click( object sender, EventArgs e)
34 {
35 SetVirtual(pLCDBuf, 0xFF , 0x300000 );
36 }
37
38 private void FormClosed( object sender, EventArgs e)
39 {
40 FreeVirtual(pLCDBuf);
41 }
42
43 private void FormLoad( object sender, EventArgs e)
44 {
45 pLCDBuf = GetVirtual( 0x4C800000 , 0x300000 );
46 }
47 }
48 }
以上代码实现了,在C#编写的应用程序中通过写显存的方式将屏幕刷成全黑或者全白。示例代码的完整解决方案下载地址:http://files.cnblogs.com/we-hjb/SysApi.rar