驱动文件:
///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: DirectIO.cpp
/// Project : DirectIO
/// 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 "DirectIO.h"
#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif
NTSTATUS DIRECTIO_DispatchCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DIRECTIO_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_DIRECTIO_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);
return status;
}
VOID DIRECTIO_DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
IoDeleteSymbolicLink(&usSymlinkName);
// Delete all the device objects
while(pdoNextDeviceObj)
{
PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
IoDeleteDevice(pdoThisDeviceObj);
}
}
NTSTATUS DispatchRead(PDEVICE_OBJECT pdo,PIRP irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(irp);
ULONG uReadLen = pStack->Parameters.Read.Length;
ULONG uMdlLen = MmGetMdlByteCount(irp->MdlAddress);//锁定有效的缓冲区长度 bytecount
ULONG uMdlOffset = MmGetMdlByteOffset(irp->MdlAddress);//mdl的首地址是 StartVa,当前这段虚拟内存对于第一个页地址的偏移量
PVOID pMdlAddress = MmGetMdlVirtualAddress(irp->MdlAddress);//当前虚拟内存的首地址 即 startVa+offset
if (uMdlLen != uReadLen)
{
status = STATUS_FILE_INVALID;
uReadLen = 0;
}else
{
PVOID pKernalAddress = MmGetSystemAddressForMdlSafe(irp->MdlAddress,NormalPagePriority);
//返回MDL映射的系统虚拟内存的地址
memset(pKernalAddress,0xCC,uReadLen);
}
irp->IoStatus.Status = status;
irp->IoStatus.Information = uReadLen;
IoCompleteRequest(irp,IO_NO_INCREMENT);
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;
// Create the device object.
if(!NT_SUCCESS(status = IoCreateDevice(
DriverObject,
0,
&usDeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pdoDeviceObj
)))
{
// Bail out (implicitly forces the driver to unload).
return status;
};
pdoDeviceObj->Flags |= DO_DIRECT_IO;//设置直接读写方式
// 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] = DIRECTIO_DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DIRECTIO_DispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
DriverObject->DriverUnload = DIRECTIO_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"\\\\.\\DIRECTIO_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 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]<<" ";
}
cout<<endl;
}
CloseHandle(hdl);
system("PAUSE");
return nRetCode;
}