驱动代码:
///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: BufferIO.cpp
/// Project : BufferIO
/// Date of creation : 2014-06-23
/// Author(s) : <author name(s)>
///
/// Purpose : <description>
///
/// Revisions:
/// 0000 [2014-06-23] Initial revision.
///
///
// $Id$
#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#ifdef __cplusplus
}; // extern "C"
#endif
#include "BufferIO.h"
typedef struct _DEVICE_EXTENSION{
PDEVICE_OBJECT pDevice;
UNICODE_STRING usDeviceName;
UNICODE_STRING usSymLinkName;
PUCHAR buffer;
ULONG uFileLen; // must low MAX_FILE_LENGTH
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
#define MAX_FILE_LENGTH 1024
#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif
NTSTATUS BUFFERIO_DispatchCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp);
if (pStack->MajorFunction == IRP_MJ_CREATE)
{
KdPrint(("DispatchCreate...."));
}else if (pStack->MajorFunction == IRP_MJ_CLOSE)
{
KdPrint(("DispatchClose...."));
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS BUFFERIO_DispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_BUFFERIO_OPERATION:
// status = SomeHandlerFunction(irpSp);
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
break;
}
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint(("DispatchDeviceControl...."));
return status;
}
VOID BUFFERIO_DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
KdPrint(("DriverUnload...."));
PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
// Delete all the device objects
while(pdoNextDeviceObj)
{
//释放扩展设备结构
PDEVICE_EXTENSION pDevExten = (PDEVICE_EXTENSION)pdoNextDeviceObj->DeviceExtension;
if (pDevExten->buffer)
{
ExFreePool(pDevExten->buffer);
pDevExten->buffer = NULL;
}
UNICODE_STRING usSymLinkName = pDevExten->usSymLinkName;
IoDeleteSymbolicLink(&usSymLinkName);
IoDeleteDevice(pDevExten->pDevice);
pdoNextDeviceObj = pdoNextDeviceObj->NextDevice;
}
}
NTSTATUS BufferID_DispathcRead(PDEVICE_OBJECT pdo,PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pdo->DeviceExtension;
ULONG uReadLen = pStack->Parameters.Read.Length;
ULONG uOffset = (ULONG)pStack->Parameters.Read.ByteOffset.QuadPart;
if (uReadLen + uOffset> MAX_FILE_LENGTH )
{
uReadLen =0;
status = STATUS_FILE_INVALID;
}else
{
memcpy(pIrp->AssociatedIrp.SystemBuffer,pDevExt->buffer+uOffset,uReadLen);
status = STATUS_SUCCESS;
}
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = uReadLen;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
KdPrint(("BufferID_DispathcRead...."));
return status;
}
NTSTATUS BufferID_DispatchWrtie(PDEVICE_OBJECT pdo,PIRP irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(irp);
ULONG uWriteLen = pStack->Parameters.Write.Length;
PDEVICE_EXTENSION pDecExt = (PDEVICE_EXTENSION)pdo->DeviceExtension;
ULONG uOffset = (ULONG)pStack->Parameters.Write.ByteOffset.QuadPart;//文件存储的偏移量,理解为当前文件指针所在位置
if (uOffset+uWriteLen > MAX_FILE_LENGTH)
{
status = STATUS_FILE_INVALID;
uWriteLen =0;
}else
{
memcpy(pDecExt->buffer+uOffset,irp->AssociatedIrp.SystemBuffer,uWriteLen);
status = STATUS_SUCCESS;
if (uWriteLen + uOffset > pDecExt->uFileLen)
{
pDecExt->uFileLen = uWriteLen+uOffset;
}
}
irp->IoStatus.Information = uWriteLen;
irp->IoStatus.Status = status;
IoCompleteRequest(irp,IO_NO_INCREMENT);
KdPrint(("BufferID_DispatchWrtie...."));
return status;
}
NTSTATUS BufferID_DispatchQUERYINFORMATION(PDEVICE_OBJECT pdo,PIRP irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(irp);
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pdo->DeviceExtension;
FILE_INFORMATION_CLASS FileInfo = pStack->Parameters.QueryFile.FileInformationClass;
//需要先判断查询的类别FILE_INFORMATION_CLASS
if (FileInfo == FileStandardInformation)
{
PFILE_STANDARD_INFORMATION pFSinfo = (PFILE_STANDARD_INFORMATION)irp->AssociatedIrp.SystemBuffer;//获取缓冲区指针
pFSinfo->EndOfFile = RtlConvertLongToLargeInteger(pDevExt->uFileLen);//将查询的结果保存在此处缓冲区
}
status =STATUS_SUCCESS;
irp->IoStatus.Information = pStack->Parameters.QueryFile.Length;//设置返回数据的长度
irp->IoStatus.Status = status;
IoCompleteRequest(irp,IO_NO_INCREMENT);
KdPrint(("BufferID_DispatchQUERYINFORMATION..."));
return status;
}
#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT pdoDeviceObj = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
pdoGlobalDrvObj = DriverObject;
PDEVICE_EXTENSION pDevExt;
// Create the device object.
if(!NT_SUCCESS(status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),//0,
&usDeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pdoDeviceObj
)))
{
// Bail out (implicitly forces the driver to unload).
return status;
};
pdoDeviceObj->Flags |= DO_BUFFERED_IO;//设置缓冲读写方式
//初始化扩展设备
pDevExt = (PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension;
pDevExt->pDevice = pdoDeviceObj;
pDevExt->usDeviceName = usDeviceName;
pDevExt->usSymLinkName = usSymlinkName;
pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool,MAX_FILE_LENGTH);
pDevExt->uFileLen = 0;
// Now create the respective symbolic link object
if(!NT_SUCCESS(status = IoCreateSymbolicLink(
&usSymlinkName,
&usDeviceName
)))
{
IoDeleteDevice(pdoDeviceObj);
return status;
}
// NOTE: You need not provide your own implementation for any major function that
// you do not want to handle. I have seen code using DDKWizard that left the
// *empty* dispatch routines intact. This is not necessary at all!
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = BUFFERIO_DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BUFFERIO_DispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_READ] = BufferID_DispathcRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = BufferID_DispatchWrtie;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = BufferID_DispatchQUERYINFORMATION;
DriverObject->DriverUnload = BUFFERIO_DriverUnload;
return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif
测试代码:
// TestDevice.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "TestDevice.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
}
HANDLE hdl = CreateFile(L"\\\\.\\BUFFERIO_DeviceName",
GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hdl == INVALID_HANDLE_VALUE)
{
CString csLog;
csLog.Format(L"CreateFile Error:%d",GetLastError());
AfxMessageBox(csLog);
return -1;
}
BYTE WrtieArr[10]={0};
for (int i=0;i<10;i++)
{
WrtieArr[i] = 0xDD;
}
DWORD dwWritenLen = 0;
BOOL bRetWrite = WriteFile(hdl,WrtieArr,10,&dwWritenLen,NULL);
if (!bRetWrite)
{
CString csLog;
csLog.Format(L"WriteFile Error:%d",GetLastError());
AfxMessageBox(csLog);
return -1;
}
BYTE ReadArr[10]={0};
DWORD dwRetLen = 0;
BOOL bRetRead = ReadFile(hdl,ReadArr,10,&dwRetLen,NULL);
if (bRetRead)
{
for (int i =0;i<dwRetLen;i++)
{
cout<<hex<<(int)ReadArr[i]<<" ";
//printf("0x%x ",bArr[i]);
}
cout<<endl;
}
CloseHandle(hdl);
system("PAUSE");
return nRetCode;
}