一個端口訪問器的編寫_第1頁
一個端口訪問器的編寫_第2頁
一個端口訪問器的編寫_第3頁
一個端口訪問器的編寫_第4頁
一個端口訪問器的編寫_第5頁
已閱讀5頁,還剩58頁未讀 繼續(xù)免費閱讀

付費下載

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

一個端口訪問器的編寫—WindowsXP驅動程序舉例VS.NET+WINXPDDK+DriverStudio3.2開發(fā)環(huán)境版本講義假設閱讀者已經熟悉VC++.NET和VS.NET(2002)的使用。如果對WindowXP驅動程序的編寫尚不熟悉,請參閱本人所編寫的《WindowsXP驅動程序編寫方法——StepbyStep》電子講義。

注意:程序中暗紅色顯示的部分是我們添加或修改過的語句,其他是DriverWorks自動生成的。藍色顯示的部分是要刪除的語句。省略號的部分是不變的。語句中T.Trace(TraceInfo,__FUNCTION__“xxxx”)這樣的語句是向調試軟件輸出信息,該信息可在DriverMonitor或其他調試監(jiān)視器中看到。2次由于一個可能是DriverStudio3.2中的BUG,所以及時生成的一個空工程項目也無法編譯通過,需要對生成的工程文件做以下手工修改:把MyIOPort項目中的sources文件中的:

TARGETLIBS=$(DDK_LIB_PATH)\ntstrsafe.lib$(DDK_LIB_PATH)\csq.lib

這一行去掉就可以編譯通過了

protected: //Memberdata

KIoRange m_ParPortIos;在“MyIOPortDevice.h”文件的

classMyIOPortDevice:publicKPnpDevice定義中添加下面的變量定義。

注意:程序中暗紅色顯示的部分是我們添加或修改過的語句,其他是DriverWorks自動生成的。藍色顯示的部分是要刪除的語句。省略號的部分是不變的。語句中T.Trace(TraceInfo,__FUNCTION__“xxxx”)這樣的語句是向調試軟件輸出信息,該信息可在DriverMonitor或其他調試監(jiān)視器中看到。修改下面函數(shù)代碼:NTSTATUSMyIOPortDevice::OnStartDevice(KIrpI){ T.Trace(TraceInfo,__FUNCTION__"++.IRP%p\n",I); NTSTATUSstatus=STATUS_SUCCESS; I.Information()=0;

//GetthelistofrawresourcesfromtheIRP PCM_RESOURCE_LISTpResListRaw=I.AllocatedResources();

//GetthelistoftranslatedresourcesfromtheIRP PCM_RESOURCE_LISTpResListTranslated=I.TranslatedResources();

//TODO:Adddevice-specificcodetoinitialize/startyourhardwaredevice.//ThebaseclasswillhandlecompletionoftheIRP

status=m_ParPortIos.Initialize(

0x00,

//PC機I/O地址空間的首地址是00H

TRUE,

//在CPUI/O空間內

8,

//設備讀寫數(shù)據的字節(jié)寬度

TRUE

//映射到系統(tǒng)空間

);T.Trace(TraceInfo,__FUNCTION__"--.IRP%p,STATUS%x\n",I,status); returnstatus;}NTSTATUSMyIOPortDevice::MYIOPORT_IOCTL_Read_Handler(KIrpI){ T.Trace(TraceInfo,__FUNCTION__"++.IRP%p\n",I); NTSTATUSstatus=STATUS_SUCCESS; ULONGoutputSize=I.IoctlOutputBufferSize();

charbuff1[50],buff2[50]; structioport{ intport; UCHARdata; }*iopt; ULONGfwLength=0;

iopt=(ioport*)I.IoctlBuffer();

//指針直接指向IRP的BUFF區(qū)域這里進

//來的時候有用戶程序的信息,出去的時候放返回信息

//顯示從應用程序得到的要讀的端口號。

T.Trace(TraceInfo,__FUNCTION__"Readportis0x%d\n",iopt->port);

下面的函數(shù)保留和添加下述語句,其他全部刪除

//從端口讀一個字節(jié)的數(shù)據

iopt->data=(UCHAR)m_ParPortIos.inb(iopt->port); fwLength=8; if(outputSize>=fwLength)

//如果讀入緩沖夠長

{ I.Information()=fwLength;

//返回信息長度

T.Trace(TraceInfo,__FUNCTION__"ReadDatais0x%d\n",iopt->data);

//顯示從應用程序得到的命令串。

} else { I.Information()=0;

//否則信息長度為0

T.Trace(TraceInfo,__FUNCTION__"buffsizetoosmall\n"); } T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning,__FUNCTION__"--.IRP%p,STATUS%x\n",I,status); returnstatus;}NTSTATUSMyIOPortDevice::MYIOPORT_IOCTL_Write_Handler(KIrpI){ T.Trace(TraceInfo,__FUNCTION__"++.IRP%p\n",I); NTSTATUSstatus=STATUS_SUCCESS;

charbuff1[50],buff2[50]; structioport{ intport; UCHARdata; }*iopt; ULONGfwLength=0; iopt=(ioport*)I.IoctlBuffer();

//指針直接指向IRP的BUFF區(qū)域這里進來的時候有用戶程序的信息,出去的時候放返回信息

T.Trace(TraceInfo,__FUNCTION__"Writeportis0x%d,Writedatais0x%d\n",iopt->port,iopt->data); //顯示從應用程序得到的命令串。

m_ParPortIos.outb(iopt->port,iopt->data);

//向端口寫一個字節(jié)的數(shù)據

I.Information()=0; T.Trace(NT_SUCCESS(status)?TraceInfo:TraceWarning,__FUNCTION__"--.IRP%p,STATUS%x\n",I,status); returnstatus;}下面我們來修改應用程序,該程序訪問硬件端口來獲得CMOS中的數(shù)據以及讓主板小喇叭發(fā)聲。首先要修改一下應用程序項目的屬性中的字符集。缺省的字符集是“使用Unicode字符集”,把它改成“未設置”。右鍵點擊接下來我們修改資源文件。下圖是系統(tǒng)自動生成的應用程序界面,這并不適合我們的需要。刪除這些控件,換上下頁顯示的控件。全部刪除StaticTextListControlButton在對話框中分別建立如圖的三個按鈕,一個列表控件(ListControl)和一個靜態(tài)文本框。其中,列表控件和按鈕的屬性如下頁的圖設置。UCHARReadOneByte(intport);//從port讀一個字節(jié)voidWriteOneByte(intport,UCHARvalue);

//向端口port寫一個字節(jié)BOOLOpenMyDevice();//打開設備voidSilence(void);//靜音voidSound(DWORDfreq);//發(fā)頻率為freq的聲音voidOnReadcmos(HWNDhDlg);//讀CMOS在“MyIOPortApp.h”文件中增加下列函數(shù)聲明在“MyIOPortApp.cpp”文件中增加下列函數(shù):UCHARReadOneByte(intport){ char buff[200]; ULONG nOutput;//CountwrittentobufOutput structioport{ intport; UCHARdata; }iopt,iopt2; iopt.port=port; if(!DeviceIoControl(g_hDevice,MYIOPORT_IOCTL_Read, &iopt, //輸出到驅動程序

sizeof(iopt),//IOCTL_INBUF_SIZE, &iopt2, //從驅動程序得到返回值

8,&nOutput,NULL) ) { sprintf(buff,"ERROR:DeviceIoControlreturns%0x.",GetLastError()); ::MessageBox(NULL,buff,"錯誤",MB_OK|MB_ICONSTOP); return0; } else { returniopt2.data; }}voidWriteOneByte(intport,UCHARvalue){ char buff[200]; ULONG nOutput; structioport{ intport; UCHARdata; }iopt,iopt2; iopt.port=port; iopt.data=value; if(!DeviceIoControl(g_hDevice, MYIOPORT_IOCTL_Write, &iopt, //輸出到驅動程序

sizeof(iopt),//IOCTL_INBUF_SIZE, &iopt2, //從驅動程序得到返回值

8,&nOutput,NULL) ) { sprintf(buff,"ERROR:DeviceIoControlreturns%0x.",GetLastError()); ::MessageBox(NULL,buff,"錯誤",MB_OK|MB_ICONSTOP); return; }}BOOLOpenMyDevice(){DWORDlastError;HDEVINFOhDeviceInfo;DWORDbufferSize;SP_DEVICE_INTERFACE_DATAinterfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATAdeviceDetail;//FinddevicesthathaveourinterfacehDeviceInfo=SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_MYIOPORT,NULL,NULL,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);if(hDeviceInfo==INVALID_HANDLE_VALUE){lastError=GetLastError();MyIOPortOutputText(_T("SetupDiGetClassDevsfailed,GetLastError()=%d"),lastError);returnFALSE;}//SetuptheinterfacedatastructinterfaceData.cbSize=sizeof(interfaceData); if(SetupDiEnumDeviceInterfaces(hDeviceInfo,NULL,(LPGUID)&GUID_DEVINTERFACE_MYIOPORT,0,&interfaceData)) { if(!SetupDiGetDeviceInterfaceDetail(hDeviceInfo,&interfaceData,NULL,0,&bufferSize,NULL)){if(GetLastError()!=ERROR_INSUFFICIENT_BUFFER){MyIOPortOutputText(_T("Error:couldn'tgetinterfacedetail,(%d)"),GetLastError()); returnFALSE;}

}

//AllocateabigenoughbuffertogetdetaildatadeviceDetail=(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(bufferSize);if(deviceDetail==NULL){

MyIOPortOutputText(_T("Error:Bufferallocationfailed"));returnFALSE;}

//Setupthedeviceinterfacestruct

deviceDetail->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

//Tryagaintogetthedeviceinterfacedetailinfoif(!SetupDiGetDeviceInterfaceDetail(hDeviceInfo,&interfaceData,deviceDetail,bufferSize,NULL,NULL)){MyIOPortOutputText(_T("Error:SetupDiGetDeviceInterfaceDetailfailed(%d)"),GetLastError());free(deviceDetail);returnFALSE;}SetupDiDestroyDeviceInfoList(hDeviceInfo); g_hDevice=CreateFile((LPCTSTR)deviceDetail->DevicePath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); if(g_hDevice==INVALID_HANDLE_VALUE) {MyIOPortOutputText(_T("Error:CreateFilefailedfordevice%s(%d)\n"),deviceDetail->DevicePath,GetLastError()); returnFALSE; }

MyIOPortOutputText(_T("Openeddevice%s"),deviceDetail->DevicePath); returnTRUE;}MyIOPortOutputText(_T("Nodevicesfound"));returnFALSE;}voidSound(DWORDfreq){ UCHARdata; if(freq>=20&&freq<=20000) { freq=1193181/freq; data=ReadOneByte(0x61); if((data&3)==0) { WriteOneByte(0x61,data|3); WriteOneByte(0x43,0xb6); } WriteOneByte(0x42,(UCHAR)(freq%256)); WriteOneByte(0x42,(UCHAR)(freq/256)); }}voidSilence(void){ UCHARdata; data=ReadOneByte(0x61); WriteOneByte(0x61,data&0xfc);}voidOnReadcmos(HWNDhDlg){

//TODO:Addyourcontrolnotificationhandlercodehere inti,it; charbuff[23]; charcmosram[128][200]={//CMOS每個字節(jié)的含義

"目前系統(tǒng)時間的秒", "報警時間秒值", "目前系統(tǒng)時間的分", "報警時間分值", "目前系統(tǒng)時間的小時", "報警時間小時值", "目前星期幾", "目前系統(tǒng)日期", "目前系統(tǒng)月份", "目前系統(tǒng)年的后兩位", "狀態(tài)寄存器A", "狀態(tài)寄存器B", "狀態(tài)寄存器C", "狀態(tài)寄存器D", "診斷狀態(tài)記錄值", "當機復位指示字節(jié)", "磁盤驅動器類型:xxxx....軟驅0類型0001=360K0010=1.2M....xxxx軟驅1類型0011=720K0100=1.44M0110=2.88M", "(海洋板)..x.....硬盤0Translate1=Yes0=No...x....硬盤1Translate1=Yes0=No.....x..1=Stepratefast0=Steprateslow......xx軟驅個數(shù)00=1個01=2個10=三個11=四個", "硬盤類型:xxxx....硬盤驅動器0的類型1111=使用19h單元....xxxx硬盤驅動器1的類型1111=使用1Ah單元", "字節(jié)x.......1=Anti-Virus硬盤Boot區(qū)寫保護0=disable.xxx....軟驅2類型....xxxx軟驅3類型", "所安裝設備的類型:xx......00=1個軟驅,01=2個軟驅,..xx....00=單顯01=CGA10=CGA11=VGA/EGA,后四位高到低是顯示、鍵盤、協(xié)處理器與軟件機使能(=1)", "基本內存容量低字節(jié),單位KB", "基本內存容量高字節(jié),單位KB", "擴充內存容量低字節(jié),單位KB", "擴充內存容量高字節(jié),單位KB", "(海洋板)硬盤驅動器0的類型", "(海洋板)硬盤驅動器1的類型", "(海洋板)顯示卡類型VGA/monochrome", "(海洋板)....xxxx啟動順序0=A:C:1=C:A:2=Screenprompt3=Autosearch4=Network.x......486-CPUCache0=disable1=enable", "(海洋板)x.......1=鍵盤使用缺省參數(shù)0=使用本單元值.xx.....鍵盤延時00=0.25秒01=0.5秒10=0.75秒11=1秒...xxxxx鍵盤重發(fā)速率,單位cps", "(海洋板)硬盤1的柱面數(shù)", "(海洋板)硬盤1的柱面數(shù)", "(海洋板)硬盤1的磁頭數(shù)", "(海洋板)硬盤1的扇區(qū)數(shù)", "(海洋板)硬盤0的柱面數(shù)", "(海洋板)硬盤0的柱面數(shù)", "(海洋板)硬盤0的磁頭數(shù)", "(海洋板)硬盤0的扇區(qū)數(shù)", "(海洋板)AT-Busclock0=16.7Mhz1=13.3Mhz2=11.1Mhz3=8.3Mhz4=6.7Mhz5=5.6Mhz6=4.2Mhz", "(海洋板)memorytype00h=60nS20h=70nS", "串口配置", "并口配置", "未使用", "未使用", "未使用", "未使用", "標準CMOS校驗和", "標準CMOS校驗和", "擴充內存容量低字節(jié),單位KB", "擴充內存容量低字節(jié),單位KB", "BCD碼的世紀值(年的高2位,如19,20等)", "信息標志", "xxxx....ShadowofD0000=Vacant....xxxxShadowofC0000=ROM", "xxxx....ShadowofF0000=ROM....xxxxShadowofE0000=Vacant", "xxxx....ShadowofD0001=WP0=Read/Write....xxxxShadowofC0001=WP0=Read/Write", "xxxx....ShadowofF0001=WP0=Read/Write....xxxxShadowofE0001=WP0=Read/Write", "內存大小,單位兆", "(內存大小有關=160/前一單元)", "口令代碼SecurityCode", "口令代碼SecurityCode", "xx......口令檢測方式0=Disable1=Setuponly2=Powerup&Setup3=Bootup&Setup..xxxxxxCold-BootDelay冷啟動延時(單位秒)*2", "xxxx....4=Fulltest5=Quickscan7=Skiptest....xx..Xfer-Modeof硬盤00=Standard1=Poll......xxXfer-Modeof硬盤12=Block3=32-BitBlock", "10h-3Dh部分單元的按字節(jié)檢查和,不包括17h,18h,19h,1Ah,26h,27h,30h,31h,32h,38h,3Ah,3Ch,3Dh單元", "10h-3Dh部分單元的按字節(jié)檢查和,不包括17h,18h,19h,1Ah,26h,27h,30h,31h,32h,38h,3Ah,3Ch,3Dh單元", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留", "保留" }; LVITEMlvitem; HWNDhWnd; hWnd=GetDlgItem(hDlg,IDC_CMOSLIST); BOOLqu; UCHARindex,value,tmp; for(i=0;i<128;i++) { lvitem.mask=LVIF_TEXT|LVIF_STATE; lvitem.iItem=i; lvitem.iSubItem=0; sprintf(buff,"%02XH",i); lvitem.pszText=buff;SendMessage(hWnd,LVM_INSERTITEM,0,(LPARAM)&lvitem); lvitem.mask=LVIF_TEXT; lvitem.iItem=i; lvitem.iSubItem=1; tmp=(UCHAR)i; index=0x80|tmp; WriteOneByte(0x70,index); value=ReadOneByte(0x71); sprintf(buff,"%02XH",value);SendMessage(hWnd,LVM_SETITEM,0,(LPARAM)&lvitem); lvitem.mask=LVIF_TEXT; lvitem.iItem=i; lvitem.iSubItem=2; lvitem.pszText=cmosram[i];SendMessage(hWnd,LVM_SETITEM,0,(LPARAM)&lvitem); } }下面增加關鍵的消息處理:LRESULTCALLBACKMyIOPortMainDlgProc(HWNDhDlg,UINTuMsg,WPARAMwParam,LPARAMlParam){……

switch(uMsg){caseWM_INITDIALOG:

g_hDevice=INVALID_HANDLE_VALUE;

//初始化ListControl

hWnd=GetDlgItem(hDlg,IDC_CMOSLIST);RECTrect;GetWindowRect(hWnd,&rect);LVCOLUMNlvm;strcpy(lvm.pszText,"偏移");lvm.cx=(rect.right-rect.left)/10;lvm.iSubItem=0;lvm.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;lvm.fmt=LVCFMT_CENTER;SendMessage(hWnd,LVM_INSERTCOLUMN,0,(LPARAM)&lvm);strcpy(lvm.pszText,"值");lvm.cx=(rect.right-rect.left)/10;lvm.iSubItem=1;lvm.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;lvm.fmt=LVCFMT_CENTER;SendMessage(hWnd,LVM_INSERTCOLUMN,1,(LPARAM)&lvm);strcpy(lvm.pszText,"偏移");lvm.cx=(rect.right-rect.left)*4/5;lvm.iSubItem=2;lvm.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM;lvm.fmt=LVCFMT_CENTER;SendMessage(hWnd,LVM_INSERTCOLUMN,2,(LPARAM)&lvm);if(OpenMyDevice()){EnableWin

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論