WinCE6.0中托管代码如何访问物理空间

时间:2022-05-16 17:32:22

      之前整理过一篇《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

      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  }

       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  }

       以上代码实现了,在C#编写的应用程序中通过写显存的方式将屏幕刷成全黑或者全白。示例代码的完整解决方案下载地址:http://files.cnblogs.com/we-hjb/SysApi.rar