天天看點

【玩轉.Net MF – 05】加載檔案系統中的Pe檔案

在遠端檔案檢視器裡,我們可以很友善地通路裝置的檔案,但是有一點,輕按兩下其中的pe檔案并不能直接執行,下面我們将為.Net MF添加這個功能。

預設情況下,.Net MF的使用者程式是放在Flash中的BLOCKTYPE_DEPLOYMENT區(參見《Flash遠端讀寫》),隻能通過VS2008進行部署。TinyCLR啟動後,直接從Flash的BLOCKTYPE_DEPLOYMENT區的加載應用程式,由于這樣的設計,是以在Flash上僅能存放一個使用者程式。

.Net MF已經支援了檔案系統,并且我們實作了遠端檔案檢視器,理論上隻要空間足夠,我們能放若幹個使用者程式,這樣問題就來了,我們能否任意執行檔案系統中的pe檔案?

.Net MF系統中的可執行檔案或子產品,其擴充名并不是exe或dll,統一為pe,唯一不同是,可執行的pe檔案中含有啟動入口辨別。pe檔案是exe和dll經過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測試程式,分别命名為Test1、Test2,相關代碼如下:

public static void Main()

{

Debug.Print("123456789");

}

public static void Main()

{

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

}           

編譯後的pe檔案分别為:Test1.pe,Test2.pe

2、              建立config.ini檔案(這步可以省略)

3、              通過遠端檔案檢視器,建立兩個目錄,Test1和Test2,分别拷入Test1.pe和Test2.pe檔案。

4、              分别輕按兩下Test1.pe和Test2.pe檔案,檢視運作結果。