• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
            數據加載中……

            MapPtrToProcess 用法 WINCE驅動分析3 轉

            可以使用下面的應用程序代碼測試這個driver,使用evc編譯。

            #include <windows.h>

            #include<Windev.h>

            #include <stdio.h>

            #include "objbase.h"

            #include "initguid.h"

             

            #include "foo.h"

             

            //char data1[10];

            int  WinMain(void)

            {

             

             

                HANDLE hnd;

                COPY_STRUCT cs[1];

                int i;

                //static char data1[10];

              auto char data1[10];

                auto char data2[10];

             

                static char* p1,*p2;

             

                //cs.pBuffer1 = (char *)malloc(10);

                //cs.pBuffer2 = (char*)malloc(10);

                //cs.nLen = 10;

             

                p1 = (char *)LocalAlloc(LPTR,10);

                p2 = (char *)malloc(10);

             

                //cs[0].pBuffer1 = (char *)malloc(10);

                //cs[0].pBuffer2 = (char*)malloc(10);

                cs[0].pBuffer1 = &data1[0];

                cs[0].pBuffer2 = &data2[0];

                cs[0].nLen = 10;

             

                memset(cs[0].pBuffer1,'a',10);

             

                hnd = CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);

             

                if(hnd==NULL)

                {

                       printf("Open device falied!\n");

                       return;

                }

             

                DeviceIoControl(hnd,IOCTL_FOO_XER,&cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);

             

                //for(i=0;i<9;i++)

                //{

                       //printf(" %c",*(cs.pBuffer2++));

                //}

             

                printf("\n");

             

                CloseHandle(hnd);

             

            //  free(cs[0].pBuffer1);

            //  free(cs[0].pBuffer2);

             

             

            }

             

            可以通過evc的單步調試看結果。好了一切都完成了,我們來看看系統是怎么工作的吧,從應用程序開始,

            CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);

             

            會調用到

            FOO_Open(DWORD dwContext, DWORD AccessCode, DWORD ShareMode)

             

            FOO_DEV_NAME名字定義在foo.h里面。

            #define       FOO_DEV_NAME L"Foo1:"

            注意后面是 1 ,這個是和注冊表的這一項匹配的

            "Index"=dword:1

             

            當調用CreateFile發生了什么,slot之間的轉換,一系列系統操作后,調用到我們自己的driver函數FOO_Open,在這個函數里我們返回了一個句柄,它可以用來存儲我們的自己driver的信息。在其它I/O操作中可以使用。

             

            Driver什么時候加載的?在注冊表里,device manager會一個個的加載,會調用到FOO_Init函數。這個函數返回一個指針,在調用FOO_Open又傳回來了,這樣我們就可以實現初始化一些自己driver的東西。

             

            接著一個重要的函數,

            DeviceIoControl(hnd,IOCTL_FOO_XER,&cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);

            調用到

            FOO_IOControl

             

            走到這里

            case IOCTL_FOO_XER:

                       if((pInBuf==NULL))

                              {

                                     SetLastError(ERROR_INVALID_PARAMETER);

                                     break;

                              }

             

                              pcs = (COPY_STRUCT*)pInBuf;

                             

                              __try{

                                     pMap1 =  MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());

                                     pMap2 =  MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());

             

                                     DEBUG_OUT(1, (TEXT("+FOO_IOControl(0x%x,0x%x)\r\n"),pcs->pBuffer1,pcs->pBuffer2));

             

                                     memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);

             

                                     bResult = TRUE;

                                     }

                              __except(EXCEPTION_EXECUTE_HANDLER){

                                     DEBUG_OUT(1,(TEXT("Exception:FOO_IOCTL\r\n")));

                                     break;                         

                              }

                             

                              break;

                       default:

                              break;

             

            這里又很多東西要研究,

             

            從應用程序傳來的參數有, control codeIOCTL_FOO_XER和一個重要的輸入參數&cs[0],它是一個指針。cs 是一個結構體,定義在FOO.H

            typedef struct {

                char* pBuffer1;

                char* pBuffer2;

                int nLen;

             

            }COPY_STRUCT;

             

            而且這個結構體里有兩個指針。

            DeviceIoControl 傳過來的指針可以用嗎?它包含的兩個指針可以直接用嗎?

             

            按照PB連接幫助文檔看,

            The operating system (OS ) manages pointers passed directly as parameters. Drivers must map all pointers contained in structures. DeviceIoControl buffers are often structures that contain data, some of which might be pointers.

            You can map a pointer contained in a structure by calling MapPtrToProcess, setting the first parameter to the pointer, and then setting the second parameter to GetCallerProcess.

            cs指針已經映射好了,但是它指向的結構里的指針我們需要自己使用MapPtrToProcess函數映射。

            這也就是:

                                     pMap1 =  MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());

                                     pMap2 =  MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());

            的由來,可是后面的代碼沒有使用pMap1pMap2。而是直接使用:

            memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);

             

            而且它還工作了,沒有出現exception。很奇怪。我第一次在一個家伙的代碼里看見這種情況,很吃驚,但是它工作的很好,是文檔出錯了?

            我們來分析一下,看看應用程序的代碼:

                COPY_STRUCT cs[1];

              auto char data1[10];

                auto char data2[10];

            cs結構和data1data2數組都是自動變量,存放在堆棧里。假設這個應用程序被加載到0x18000000位置的slot里,那么他們的地址都是0x18XXXXXX。不熟悉wince memory architecture的可以看看資料,了解一下slot。當調用了

            DeviceIoControl,按照文檔的說法,cs指針得到了轉換,因為從應用程序的進程轉到了device.exe進程,而device進程又是當前的運行的進程,被映射到了slot0,系統負責轉換cs指針。而cs包含的pBuffer1pBuffer2是沒有映射不能直接用的。

            事實上,我們傳過來的指針根本就是不需要映射,因為他們都是0x18xxxxxx,在應用程序的slot里,所以只要device.exe有訪問應用程序的權限,就可以了。而這個權限,系統已經幫我們設置好了。

             

            那什么情況下要自己映射呢?

            如果應用程序在定義 data1data2使用static關鍵字,或者使用LocalAllocHeapAlloc的時候,一定要自己映射cs里的指針。

            在應用程序里這樣寫:

                cs.pBuffer1 = (char *)malloc(10);

                cs.pBuffer2 = (char*)malloc(10);

                cs.nLen = 10;

            如果不使用MapPtrToProcess完成映射,那就出現data abort exception.

             

            為什么呢?

            因為這些變量都是在堆里分配的,而當應用程序運行時,被映射到slot0,堆的地址也就是處于slot的范圍內,傳遞到device.exe后,device.exe被映射到了slot0,這個時候必須要將應用程序的指針映射回應用程序所在的slot。否則訪問的是device.exe的空間,會發生不可知道的結果。

             

            驗證一下上面說的地址分配問題。

             

            我們這樣定義

            COPY_STRUCT cs[1];

              static char data1[10]; 堆里

              auto char data2[10];   棧里

             

            這樣賦值:

             

              cs[0].pBuffer1 = &data1[0];

              cs[0].pBuffer2 = &data2[0];

              cs[0].nLen = 10;

             

            調試信息:

            cs[0].pBuffer1 = &data1[0];

             

            180112D0   ldr       r2, [pc, #0xD0]

            180112D4   str       r2, [sp, #0x10]

             

            讀取&data1[0]使用的是PC作為基址,而此時的應用程序處于運行階段映射到slot0,那么pc也就在0~01ffffff范圍,我的調試結果是在0x000112D0+8,使用的是arm,流水線機制,當前指令地址+8才是pc值。

             

            143:      cs[0].pBuffer2 = &data2[0];

            180112D8   add       r0, sp, #0x20

            180112DC   str       r0, [sp, #0x14]

            讀取&data2[0]采用的是sp作為基址,sp在應用程序加載到slot的時候就確定了的。所以保持了在應用程序slot的值,處于0x18xxxxxx范圍。

             

            我們看到因為winceslot機制,我們有時候需要映射,有時候不需要。所以wince文檔說結構里的指針要映射。畢竟你不知道應用程序怎么寫。

            當然,你可以根本不映射,只要把那個結構屏蔽調,寫一個STATIC LIBRARY給用戶使用,自己保證使用正確的地址分配就可以了。上面我說的那個家伙就是這么干的。

             

            好了,接著

            調用:

              CloseHandle(hnd);

            程序結束了,完成了一次簡單的拷貝。

             

            這個框架完成了,driver的基本接口設計,強調了內存指針的使用問題。但是相對于一個真正的driver,還缺少點東西,就是訪問硬件的方法。下面繼續討論如何訪問硬件。

            posted on 2008-08-14 09:28 井泉 閱讀(1512) 評論(0)  編輯 收藏 引用 所屬分類: c code

            久久777国产线看观看精品| 久久亚洲国产精品五月天婷| 久久99热这里只有精品国产| 欧美精品九九99久久在观看| 亚洲欧美日韩中文久久| 欧美亚洲国产精品久久高清| 久久久一本精品99久久精品88| 久久精品国产2020| 天天久久狠狠色综合| 日韩精品久久久久久久电影| 精品国产一区二区三区久久久狼 | 欧美久久综合性欧美| 久久影院午夜理论片无码| 亚洲精品无码久久久久| 久久99国产精品成人欧美| 亚洲精品乱码久久久久久中文字幕 | 久久综合久久鬼色| 久久精品国产久精国产思思| 久久有码中文字幕| 人人狠狠综合久久亚洲婷婷| 久久九九兔免费精品6| 久久激情亚洲精品无码?V| 精品一区二区久久久久久久网站| 久久久久久精品成人免费图片| 精品久久久久久无码人妻热| 国产一区二区精品久久| 亚洲级αV无码毛片久久精品| 久久久久亚洲AV成人网人人软件| AV狠狠色丁香婷婷综合久久| 精品久久久无码人妻中文字幕豆芽| 久久久久亚洲精品日久生情 | 精品久久久久成人码免费动漫| 999久久久国产精品| 国产精品欧美久久久天天影视| 亚洲AV无码久久精品蜜桃| 99久久夜色精品国产网站| 一级A毛片免费观看久久精品| 欧洲性大片xxxxx久久久| 久久亚洲高清综合| 一97日本道伊人久久综合影院| 一本久道久久综合狠狠躁AV|