日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WinCE驱动的动态加载

發布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WinCE驱动的动态加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

//=====================================================================
//TITLE:
//??? WinCE驅動的動態加載
//AUTHOR:
//??? norains
//DATE:
//??? Monday 22- February-2010
//Environment:
//???? WINDOWS CE 5.0
//=====================================================================

????

???? WinCE驅動的調試,很多人的第一感覺就是:編寫好DLL文件,接著在PB中添加相關注冊表信息,然后將DLL文件包含進系統,最后生成系統,下載,調試。如果有誤,那么依次按步驟重來。
?
  其實這種繁瑣的操作完全可以不必要,因為在WinCE下驅動是可以動態加載和卸載的。
  
  驅動的加載和卸載非常簡單,我們只需要如下兩個函數:
  

[cpp]?view plaincopy
  • HANDLE?ActivateDeviceEx(??
  • ??LPCWSTR?lpszDevKey,???
  • ??LPCVOID?lpRegEnts,???
  • ??DWORD?cRegEnts,???
  • ??LPVOID?lpvParam??
  • );??
  • ??
  • BOOL?DeactivateDevice(??
  • ??HANDLE?hDevice??
  • );??

  •   
      前者是加載,后者是卸載。
      
      我們首先來看一下加載函數。這函數很簡單,lpszDevKey指向的是驅動信息在注冊表的位置。比如,我之前文章所提到的虛擬串口的驅動的注冊表信息如下:
      
      [HKEY_LOCAL_MACHINE/Drivers/Builtin/VirtualSerial]
      ??? "Prefix"="VSP"
      ??? "Dll"="VirtualSerial.dll"
      ??? "Order"=dword:0
      ??? "Index"=dword:1
      ??? "Map_Port"="COM1:"
      
      那么對于這個信息而言,lpszDevkey的取值為TEXT("Drivers//Builtin//VirtualSerial")。對于系統而言,驅動的Root Key為HKEY_LOCAL_MACHINE,故這里并不需要特別指出。換而言之,驅動的信息只能放置于HKEY_LOCAL_MACHINE,因為我們無法另外指定Root Key。
      
      接下來再看看別的參數。lpRegEnts和cRegEnts是和BUS有關的,但我們接下來的例子并沒有用上,所以這里直接可以忽略,直接賦值NULL即可。其實,如果不使用這兩個形參的話,我們還可以選擇ActivateDevice。
      
      lpvParam指向的是傳給驅動XXX_Init函數的形參,如果有特別需求,我們可以通過該指針進行傳遞。
      
      函數功能很簡單。我們寫一個功能簡單的驅動,來測試該函數是否有效。


      驅動代碼如下:  
      

    [cpp]?view plaincopy
  • DWORD?g_dwParam?=?0;??
  • std::wstring?g_strContext;??
  • ??
  • BOOL?WINAPI?DllEntry(HANDLE?hInstDll,?DWORD?dwReason,?LPVOID?lpvReserved)??
  • {??
  • ????switch?(?dwReason?)???
  • ????{??
  • ????????case?DLL_PROCESS_ATTACH:??
  • ????????break;??
  • ????}??
  • ????return?TRUE;??
  • }??
  • ??
  • ??
  • ??
  • DWORD?FKE_Init(??
  • ??LPCTSTR?pContext,??
  • ??LPCVOID?lpvBusContext??
  • )??
  • {??
  • ?printf("FKE_Init?!/r/n");??
  • ??
  • ?if(pContext?!=?NULL)??
  • ?{??
  • ??g_strContext?=?pContext;??
  • ?}??
  • ??
  • ?if(lpvBusContext?!=?NULL)??
  • ?{??
  • ??g_dwParam?=?*(reinterpret_cast<const?DWORD?*>(lpvBusContext));??
  • ?}??
  • ?return?TRUE;??
  • }??
  • ??
  • ??
  • BOOL?FKE_Deinit(??
  • ????DWORD?dwContext???????
  • ????)??
  • {??
  • ????
  • ?printf("FKE_Deinit?!/r/n");??
  • ?return?TRUE;??
  • }??
  • ??
  • DWORD?FKE_Open(??
  • ????DWORD?dwData,??
  • ????DWORD?dwAccess,??
  • ????DWORD?dwShareMode??
  • ????)??
  • {??
  • ?return?TRUE;??
  • }??
  • ??
  • BOOL?FKE_Close(DWORD?dwHandle)??
  • {??
  • ?return?TRUE;??
  • }??
  • ??
  • ??
  • BOOL?FKE_IOControl(??
  • ????DWORD?dwHandle,??
  • ????DWORD?dwIoControlCode,??
  • ????PBYTE?pBufIn,??
  • ????DWORD?dwBufInSize,??
  • ????PBYTE?pBufOut,??
  • ????DWORD?dwBufOutSize,??
  • ????PDWORD?pBytesReturned??
  • ????)??
  • {???
  • ?return?FALSE;??
  • }??
  • ??
  • DWORD?FKE_Read(DWORD?dwHandle,?LPVOID?pBuffer,?DWORD?dwNumBytes)??
  • {??
  • ?std::vector<TCHAR>?vtVal(MAX_PATH,0);??
  • ?_stprintf(&vtVal[0],TEXT("Context:%s/r/n?Parameter:%d/r/n"),g_strContext.c_str(),g_dwParam);??
  • ??
  • ?int?iLen?=?_tcslen(&vtVal[0]);??
  • ?memcpy(pBuffer,&vtVal[0],iLen?*?2);??
  • ???
  • ?return?iLen;??
  • }??
  • ??
  • DWORD?FKE_Write(DWORD?dwHandle,?LPCVOID?pBuffer,?DWORD?dwNumBytes)??
  • {??
  • ?return?0;??
  • }??
  • ??
  • ??
  • DWORD?FKE_Seek(DWORD?dwHandle,?long?lDistance,?DWORD?dwMoveMethod)??
  • {??
  • ?return?FALSE;??
  • }??
  • ??
  • void?FKE_PowerUp(void)??
  • {??
  • ?return;??
  • }??
  • ??
  • void?FKE_PowerDown(void)??
  • {??
  • ?return;??
  • }??
  • ??
  •   ??

  •   代碼意思很簡單,就是在加載和卸載的時候,分別打印信息。然后還有兩個全局變量,一個是g_strContext,用來保存成功加載時的注冊表位置;另一個是g_dwParam,用來保存通過ActivateDeviceEx函數傳遞的第4個形參。而這兩個全局變量的數值,之后我們可以通過ReadFile函數獲得。只不過FKE_Read函數健壯性不高,沒有判斷緩沖區是否為空。但作為測試,還是夠了。
      
      驅動方面大致如此,我們再來實例看看如何加載驅動。因為驅動的加載涉及到注冊表的寫入,所以我這里直接采用了CReg類。關于該類的代碼,詳情可參見:(http://blog.csdn.net/norains/archive/2007/06/20/1659925.aspx)
      
      我們先寫注冊表信息:  

    [cpp]?view plaincopy
  • ????#define?DEV_KEY?TEXT("Drivers//Builtin//FakeDriver")??
  • ??
  • CReg?reg;??
  • reg.Create(HKEY_LOCAL_MACHINE,DEV_KEY);??
  • reg.SetDW(TEXT("Order"),0);??
  • reg.SetDW(TEXT("Index"),1);??
  • reg.SetSZ(TEXT("Prefix"),TEXT("FKE"));??
  • reg.SetSZ(TEXT("Dll"),TEXT("//Windows//Driver.dll"));??
  •   
      
      稍微說一下注冊表寫入數值的意思。Order是加載的順序,其實手工加載的話可以無視該字段。Index是打開時的序號,與此相關的還有Prefix,為驅動名。Dll則簡單了,則是我們編譯好的驅動的存放路徑。
      
      接下來就簡單多了,我們加載驅動,然后傳遞一個DWORD的數值作為形參:  
    [cpp]?view plaincopy
  • DWORD?dwParam?=?89;??
  • HANDLE?hd?=?ActivateDeviceEx(DEV_KEY,NULL,0,&dwParam);??
  • ??
  • HANDLE?hDriver?=?CreateFile(TEXT("FKE1:"),??
  • ???GENERIC_READ?|?GENERIC_READ,??
  • ???0,??
  • ???NULL,??
  • ???OPEN_EXISTING,??
  • ???FILE_ATTRIBUTE_NORMAL,??
  • ???NULL);??
  • ??
  • std::vector<TCHAR>?vtBuf(MAX_PATH);??
  • DWORD?dwRead?=?0;??
  • ReadFile(hDriver,&vtBuf[0],vtBuf.size(),&dwRead,NULL);??
  • ??
  • ????CloseHandle(hDriver);??
  •  ??

  •   如果運行這段代碼,你則會看到ReadFile之后,vtBuf則會存儲到相應的數值。在我的平臺上,某次運行時的數值如下:
      
      Context:Driver/Active/37 Parameter:89
      
      最后,就是卸載驅動。這個最簡單,直接傳遞ActivateDeviceEx執行成功后返回的數值即可:

    總結

    以上是生活随笔為你收集整理的WinCE驱动的动态加载的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。