现在的位置: 首页 > 综合 > 正文

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

2013年04月09日 ⁄ 综合 ⁄ 共 3869字 ⁄ 字号 评论关闭

      之前整理过一篇《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, 0x000x300000);
31         }
32 
33         private void White_Click(object sender, EventArgs e)
34         {
35             SetVirtual(pLCDBuf, 0xFF0x300000);
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(0x4C8000000x300000);
46         }
47     }
48 }

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

抱歉!评论已关闭.