生活随笔
收集整理的這篇文章主要介紹了
获取WinCE已加载驱动的信息
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
//=====================================================================
//TITLE:
//??? WinCE驅(qū)動的動態(tài)加載
//AUTHOR:
//??? norains
//DATE:
//??? Monday 22- February-2010
//Environment:
//???? WINDOWS CE 5.0
//=====================================================================
????
???? WinCE驅(qū)動的調(diào)試,很多人的第一感覺就是:編寫好DLL文件,接著在PB中添加相關(guān)注冊表信息,然后將DLL文件包含進(jìn)系統(tǒng),最后生成系統(tǒng),下載,調(diào)試。如果有誤,那么依次按步驟重來。
?
其實這種繁瑣的操作完全可以不必要,因為在WinCE下驅(qū)動是可以動態(tài)加載和卸載的。
驅(qū)動的加載和卸載非常簡單,我們只需要如下兩個函數(shù):
[cpp]?view plaincopy
HANDLE?ActivateDeviceEx(?? ??LPCWSTR?lpszDevKey,??? ??LPCVOID?lpRegEnts,??? ??DWORD?cRegEnts,??? ??LPVOID?lpvParam?? );?? ?? BOOL?DeactivateDevice(?? ??HANDLE?hDevice?? );??
前者是加載,后者是卸載。
我們首先來看一下加載函數(shù)。這函數(shù)很簡單,lpszDevKey指向的是驅(qū)動信息在注冊表的位置。比如,我之前文章所提到的虛擬串口的驅(qū)動的注冊表信息如下:
[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")。對于系統(tǒng)而言,驅(qū)動的Root Key為HKEY_LOCAL_MACHINE,故這里并不需要特別指出。換而言之,驅(qū)動的信息只能放置于HKEY_LOCAL_MACHINE,因為我們無法另外指定Root Key。
接下來再看看別的參數(shù)。lpRegEnts和cRegEnts是和BUS有關(guān)的,但我們接下來的例子并沒有用上,所以這里直接可以忽略,直接賦值NULL即可。其實,如果不使用這兩個形參的話,我們還可以選擇ActivateDevice。
lpvParam指向的是傳給驅(qū)動XXX_Init函數(shù)的形參,如果有特別需求,我們可以通過該指針進(jìn)行傳遞。
函數(shù)功能很簡單。我們寫一個功能簡單的驅(qū)動,來測試該函數(shù)是否有效。
驅(qū)動代碼如下:
[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函數(shù)傳遞的第4個形參。而這兩個全局變量的數(shù)值,之后我們可以通過ReadFile函數(shù)獲得。只不過FKE_Read函數(shù)健壯性不高,沒有判斷緩沖區(qū)是否為空。但作為測試,還是夠了。
驅(qū)動方面大致如此,我們再來實例看看如何加載驅(qū)動。因為驅(qū)動的加載涉及到注冊表的寫入,所以我這里直接采用了CReg類。關(guān)于該類的代碼,詳情可參見:(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"));??
稍微說一下注冊表寫入數(shù)值的意思。Order是加載的順序,其實手工加載的話可以無視該字段。Index是打開時的序號,與此相關(guān)的還有Prefix,為驅(qū)動名。Dll則簡單了,則是我們編譯好的驅(qū)動的存放路徑。
接下來就簡單多了,我們加載驅(qū)動,然后傳遞一個DWORD的數(shù)值作為形參:
[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則會存儲到相應(yīng)的數(shù)值。在我的平臺上,某次運行時的數(shù)值如下:
Context:Driver/Active/37 Parameter:89
最后,就是卸載驅(qū)動。這個最簡單,直接傳遞ActivateDeviceEx執(zhí)行成功后返回的數(shù)值即可:
總結(jié)
以上是生活随笔為你收集整理的获取WinCE已加载驱动的信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。