zoukankan      html  css  js  c++  java
  • 【玩转.Net MF – 05】加载文件系统中的Pe文件

    远程文件查看器里,我们可以很方便地访问设备的文件,但是有一点,双击其中的pe文件并不能直接执行,下面我们将为.Net MF添加这个功能。

    默认情况下,.Net MF的用户程序是放在Flash中的BLOCKTYPE_DEPLOYMENT区(参见《Flash远程读写》),只能通过VS2008进行部署。TinyCLR启动后,直接从FlashBLOCKTYPE_DEPLOYMENT区的加载应用程序,由于这样的设计,所以在Flash上仅能存放一个用户程序。

    .Net MF已经支持了文件系统,并且我们实现了远程文件查看器,理论上只要空间足够,我们能放若干个用户程序,这样问题就来了,我们能否任意执行文件系统中的pe文件?

    .Net MF系统中的可执行文件或模块,其扩展名并不是exedll,统一为pe,唯一不同是,可执行的pe文件中含有启动入口标识。pe文件是exedll经过MetaDataProcessor.exe文件再加工而来。

    实现思路其实很简单:第一、分别把不同的用户程序,放到不同目录中去;第二、在根目录建立一个config.ini纯文本文件,里面有一条记录:Startup=\xxx,标识启动项;第三、修改TinyCLR代码,让其从config.ini中的指定目录处加载用户程序。

     TinyCLR中的Code修改如下(CLRStartup.cpp文件),枚举指定目录中的pe文件,并加载之。

     HRESULT LoadDeploymentAssemblies()

     {

         TINYCLR_HEADER();

     

         WCHAR current_file[256];

          WCHAR temp_path[256];

         UINT32 findHandle=NULL;

          FileSystemVolume* volume = NULL;

         STREAM_DRIVER_INTERFACE* streamDriver=volume->m_streamDriver;

          HRESULT ret;

     

         volume = FileSystemVolumeList::GetFirstVolume();

          if(volume ==NULL)

          {

                TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

          }

          streamDriver=volume->m_streamDriver;

             if(streamDriver==NULL)

          {

                TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

          }

        //--

        UINT32 rHandle = NULL; 

          if(streamDriver->Open(&volume->m_volumeId, L"\\config.ini", &rHandle) == S_OK && rHandle != NULL)

          {          

                  INT64 FileSize;

                  int bytesread=0;

               streamDriver->GetLength(rHandle,&FileSize);

                    if(FileSize>510 || FileSize<20)

                    {

                         streamDriver->Close(rHandle);

                    if(FileSize == 0) debug_printf("Can't find config.ini!\r\n");

                         else debug_printf("Load Application failed(2)!\r\n");

                      TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

                    }          

             if(streamDriver->Read(rHandle, (BYTE *)temp_path,(INT32)FileSize ,&bytesread) != S_OK && bytesread!=(UINT32)FileSize)

                {

                        streamDriver->Close(rHandle); 

                     debug_printf("Load Application failed(3)!\r\n");

                     TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

                }

                streamDriver->Close(rHandle);          

     

                if(temp_path[0]!=0xFEFF || temp_path[8]!=0x3D)

                {

                     TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

                }

                memcpy(current_file, &temp_path[9],FileSize-9*2 );

                temp_path[FileSize/2-9] = 0;

                for(int i=FileSize/2-10;i>0; i--)

                {

                      if(current_file[i]==0x0D ||current_file[i]==0x0A) current_file[i] = 0;

                }

          }

            else

          {

                TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);

            }

            //--

            ret = volume->FindOpen(current_file,&findHandle);

          if(findHandle==NULL || ret != S_OK)

     {

               TINYCLR_SET_AND_LEAVE(CLR_E_FAIL);   

          } 

        //--

        FS_FILEINFO findData;

        int pathsize=wcslen(current_file);

          current_file[pathsize++]='\\';

        

        findData.FileName=(UINT16 *)&current_file[pathsize];

        findData.FileNameSize = 200;

          memset(findData.FileName,0,(findData.FileNameSize+1)*2);

                

          BOOL found=FALSE;

          ret = volume->FindNext(findHandle,&findData,&found);

          while( ret==S_OK && found)

          {        TINYCLR_CHECK_HRESULT(ContiguousBlockAssemblies(volume,current_file));         

               memset(temp_path,0,findData.FileNameSize+1);

                ret = volume->FindNext(findHandle,&findData,&found);

          }

        //--

        volume->FindClose(findHandle);    

          TINYCLR_NOCLEANUP();          

    }

    远程文件查看器中的代码稍加修改,就能支持双击运行。在双击事件里,一是修改config.ini文件中的运行目录,二是重启TinyCLR,让其加载指定目录中的程序。由于相关代码比较简单,这里就不贴了。

    下面来演示一下最终成果。

    1、              新建两个.Net MF测试程序,分别命名为Test1Test2,相关代码如下:

    public static void Main()

    {

    Debug.Print("123456789");

    }

    public static void Main()

    {

    Debug.Print("abcdefghijklmn!!!");

    }

    编译后的pe文件分别为:Test1.pe,Test2.pe

    2、              新建config.ini文件(这步可以省略)

    3、              通过远程文件查看器,新建两个目录,Test1Test2,分别拷入Test1.peTest2.pe文件。

    1

    4、              分别双击Test1.peTest2.pe文件,查看运行结果。

    2 

     

     

  • 相关阅读:
    双击导航栏自动滑动ListView到顶部
    及时取消代码中的AsyncTask
    Nubia Z9 mini使用体验
    特殊情况特殊处理
    SharePreferences的DB实现
    时下手机和p2p理财的共同点
    小米空气净化器体验
    消息框架的一种实现
    刷了MIUI的手机在OSX下连接USB调试的方法
    16个最佳响应式HTML5框架
  • 原文地址:https://www.cnblogs.com/yefanqiu/p/1676818.html
Copyright © 2011-2022 走看看