生活随笔
收集整理的這篇文章主要介紹了
寒江独钓-串口过滤
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
直接上源碼
注釋什么的都在源碼上:
因為沒有 ?打印機 ?實現 ? 下載程序 ? 超級終端 ?可以看到
http://download.csdn.net/download/yfly13/863785
#include <ntddk.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>#ifndef SetFlag
#define SetFlag(_F,_SF) ((_F) |= (_SF))
#endif
#ifndef ClearFlag
#define ClearFlag(_F,_SF) ((_F) &= ~(_SF))
#endif#define CCP_MAX_COM_ID 32 //作者假設計算機上最多有32個串口// 過濾設備和真實設備
static PDEVICE_OBJECT s_fltobj[CCP_MAX_COM_ID] = { 0 };
static PDEVICE_OBJECT s_nextobj[CCP_MAX_COM_ID] = { 0 };// 打開一個端口設備
PDEVICE_OBJECT ccpOpenCom(ULONG id,NTSTATUS *status)
{//外面輸入的是串口ID,這里會改寫成字符串的形式UNICODE_STRING name_str;static WCHAR name[32] = { 0 };PFILE_OBJECT fileobj = NULL;PDEVICE_OBJECT devobj = NULL;// 輸入字符串。memset(name,0,sizeof(WCHAR)*32);RtlStringCchPrintfW(name,32,L"\\Device\\Serial%d",id);RtlInitUnicodeString(&name_str,name);// 打開設備對象*status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);if (*status == STATUS_SUCCESS)//fileobj 這里無用ObDereferenceObject(fileobj);//必須解除引用 不然會內存泄漏return devobj;
}NTSTATUS
ccpAttachDevice(PDRIVER_OBJECT driver, PDEVICE_OBJECT oldobj, //通過名稱得到的設備對象PDEVICE_OBJECT *fltobj, //過濾設備PDEVICE_OBJECT *next) //真實設備
{NTSTATUS status;PDEVICE_OBJECT topdev = NULL;// 生成設備,然后綁定之。status = IoCreateDevice(driver,0,NULL, //過濾設備一般不需要名稱oldobj->DeviceType, //保持和被綁定的一樣0,FALSE,fltobj);//過濾設備if (status != STATUS_SUCCESS)return status;// 拷貝重要標志位。if(oldobj->Flags & DO_BUFFERED_IO)(*fltobj)->Flags |= DO_BUFFERED_IO;if(oldobj->Flags & DO_DIRECT_IO)(*fltobj)->Flags |= DO_DIRECT_IO;if(oldobj->Flags & DO_BUFFERED_IO)(*fltobj)->Flags |= DO_BUFFERED_IO;if(oldobj->Characteristics & FILE_DEVICE_SECURE_OPEN)(*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;(*fltobj)->Flags |= DO_POWER_PAGABLE;// 綁定一個設備到另一個設備上topdev = IoAttachDeviceToDeviceStack(*fltobj,oldobj);//過濾設備, 要被綁定的設備棧中的設備if (topdev == NULL){// 如果綁定失敗了,銷毀設備,重新來過。IoDeleteDevice(*fltobj);*fltobj = NULL;status = STATUS_UNSUCCESSFUL;return status;}*next = topdev;//返回的最終被綁定的設備// 設置這個設備已經啟動。(*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;return STATUS_SUCCESS;
}// 這個函數綁定所有的串口。
void ccpAttachAllComs(PDRIVER_OBJECT driver)
{ULONG i;PDEVICE_OBJECT com_ob;NTSTATUS status;for(i = 0;i<CCP_MAX_COM_ID;i++){// 獲得object對象。com_ob = ccpOpenCom(i,&status);if(com_ob == NULL)continue;// 在這里綁定。并不管綁定是否成功。ccpAttachDevice(driver,com_ob,&s_fltobj[i],&s_nextobj[i]);// 取消object引用。}
}#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)void ccpUnload(PDRIVER_OBJECT drv)
{ULONG i;LARGE_INTEGER interval;// 首先解除綁定for(i=0;i<CCP_MAX_COM_ID;i++){if(s_nextobj[i] != NULL)IoDetachDevice(s_nextobj[i]);}// 睡眠5秒。等待所有irp處理結束interval.QuadPart = (5*1000 * DELAY_ONE_MILLISECOND); KeDelayExecutionThread(KernelMode,FALSE,&interval);// 刪除這些設備for(i=0;i<CCP_MAX_COM_ID;i++){if(s_fltobj[i] != NULL)IoDeleteDevice(s_fltobj[i]);}KdPrint(("enter my unliad\n"));
}NTSTATUS ccpDispatch(PDEVICE_OBJECT device,PIRP irp)
{PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);NTSTATUS status;ULONG i,j;// 首先得知道發送給了哪個設備。設備一共最多CCP_MAX_COM_ID// 個,是前面的代碼保存好的,都在s_fltobj中。for(i=0;i < CCP_MAX_COM_ID;i++){if(s_fltobj[i] == device){ // 所有電源操作,全部直接放過。if(irpsp->MajorFunction == IRP_MJ_POWER){// 直接發送,然后返回說已經被處理了。PoStartNextPowerIrp(irp);IoSkipCurrentIrpStackLocation(irp);return PoCallDriver(s_nextobj[i],irp);}// 此外我們只過濾寫請求。寫請求的話,獲得緩沖區以及其長度。// 然后打印一下。if(irpsp->MajorFunction == IRP_MJ_WRITE){// 如果是寫,先獲得長度ULONG len = irpsp->Parameters.Write.Length;// 然后獲得緩沖區PUCHAR buf = NULL;if(irp->MdlAddress != NULL)buf = (PUCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);elsebuf = (PUCHAR)irp->UserBuffer;if(buf == NULL)buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;// 打印內容for(j=0;j<len;++j){DbgPrint("comcap: Send Data: %2x\r\n", buf[j]);}}// 這些請求直接下發執行即可。我們并不禁止或者改變它。IoSkipCurrentIrpStackLocation(irp);//將請求發送到對應的真是設備,s_nextobj為真實設備保存地return IoCallDriver(s_nextobj[i],irp);}}// 如果根本就不在被綁定的設備中,那是有問題的,直接返回參數錯誤。irp->IoStatus.Information = 0;irp->IoStatus.Status = STATUS_INVALID_PARAMETER;IoCompleteRequest(irp,IO_NO_INCREMENT);return STATUS_SUCCESS;
}NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{size_t i;// 所有的分發函數都設置成一樣的。KdPrint(("enter my driverentry\n"));for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++){driver->MajorFunction[i] = ccpDispatch;}// 支持動態卸載。driver->DriverUnload = ccpUnload;// 綁定所有的串口。ccpAttachAllComs(driver);// 直接返回成功即可。return STATUS_SUCCESS;
}
總結
以上是生活随笔為你收集整理的寒江独钓-串口过滤的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。