• <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
            數(shù)據(jù)加載中……

            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的單步調試看結果。好了一切都完成了,我們來看看系統(tǒng)是怎么工作的吧,從應用程序開始,

            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發(fā)生了什么,slot之間的轉換,一系列系統(tǒng)操作后,調用到我們自己的driver函數(shù)FOO_Open,在這個函數(shù)里我們返回了一個句柄,它可以用來存儲我們的自己driver的信息。在其它I/O操作中可以使用。

             

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

             

            接著一個重要的函數(shù),

            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;

             

            這里又很多東西要研究,

             

            從應用程序傳來的參數(shù)有, control codeIOCTL_FOO_XER和一個重要的輸入?yún)?shù)&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函數(shù)映射。

            這也就是:

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

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

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

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

             

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

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

                COPY_STRUCT cs[1];

              auto char data1[10];

                auto char data2[10];

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

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

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

             

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

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

            在應用程序里這樣寫:

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

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

                cs.nLen = 10;

            如果不使用MapPtrToProcess完成映射,那就出現(xiàn)data abort exception.

             

            為什么呢?

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

             

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

             

            我們這樣定義

            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,還缺少點東西,就是訪問硬件的方法。下面繼續(xù)討論如何訪問硬件。

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

            久久精品亚洲福利| 一本色综合网久久| 国产免费福利体检区久久 | 亚洲性久久久影院| 久久九九兔免费精品6| 国产精品国色综合久久| 国产精品内射久久久久欢欢| 国内精品伊人久久久久妇| 国产午夜精品久久久久免费视| 久久久国产精品福利免费 | 久久精品国产免费一区| 久久午夜福利电影| 无码国产69精品久久久久网站| 国产精品九九久久免费视频 | 久久免费大片| 国产精品一久久香蕉产线看| 久久中文字幕视频、最近更新 | 国产午夜精品久久久久九九电影| 精品综合久久久久久97| 欧美久久精品一级c片片| 国产成人精品综合久久久久 | 久久r热这里有精品视频| 思思久久精品在热线热| 久久综合狠狠综合久久激情 | 99久久夜色精品国产网站| 性高朝久久久久久久久久| 伊人热人久久中文字幕| 潮喷大喷水系列无码久久精品| 日本五月天婷久久网站| 性做久久久久久免费观看| 99热精品久久只有精品| 99久久精品国产一区二区| 精品久久一区二区三区| 国产美女久久久| 99热成人精品免费久久| 国产成人香蕉久久久久| 国产精品成人精品久久久 | 一本色道久久88精品综合| 三级三级久久三级久久| av色综合久久天堂av色综合在| 精品熟女少妇AV免费久久|