驱动层
#include <ntddk.h>
#include <windef.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
IoDeleteSymbolicLink(&SymbolicLinkName);//删除连接
IoDeleteDevice(pDriverObject->DeviceObject);//释放驱动对象
//驱动卸载的时候显示
KdPrint(("Goodbye driver\n"));
}
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
static char* irpname[] = {
"IRP_MJ_CREATE ",
"IRP_MJ_CREATE_NAMED_PIPE ",
"IRP_MJ_CLOSE ",
"IRP_MJ_READ ",
"IRP_MJ_WRITE ",
"IRP_MJ_QUERY_INFORMATION ",
"IRP_MJ_SET_INFORMATION ",
"IRP_MJ_QUERY_EA ",
"IRP_MJ_SET_EA ",
"IRP_MJ_FLUSH_BUFFERS ",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION ",
"IRP_MJ_DIRECTORY_CONTROL ",
"IRP_MJ_FILE_SYSTEM_CONTROL ",
"IRP_MJ_DEVICE_CONTROL ",
"IRP_MJ_INTERNAL_DEVICE_CONTROL ",
"IRP_MJ_SHUTDOWN ",
"IRP_MJ_LOCK_CONTROL ",
"IRP_MJ_CLEANUP ",
"IRP_MJ_CREATE_MAILSLOT ",
"IRP_MJ_QUERY_SECURITY ",
"IRP_MJ_SET_SECURITY ",
"IRP_MJ_POWER ",
"IRP_MJ_SYSTEM_CONTROL ",
"IRP_MJ_DEVICE_CHANGE ",
"IRP_MJ_QUERY_QUOTA ",
"IRP_MJ_SET_QUOTA ",
"IRP_MJ_PNP ",
"IRP_MJ_PNP_POWER ",
"IRP_MJ_MAXIMUM_FUNCTION "
};
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
KdPrint(("%s\n", irpname[stack->MajorFunction]));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;//设置返回状态,告诉操作是成功还是失败
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return STATUS_SUCCESS;
};
NTSTATUS DispatchRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
PVOID pReadBuffer = NULL;
NTSTATUS status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
ULONG Length;
ULONG uMin;
KdPrint(("读操作\n"));
__try
{
if (stack->Parameters.Read.Length > 512)
{
//ULONG uHelloStr = (wcslen(L"这是一段来自内核空间的字符串") + 1) * sizeof(WCHAR);
//uMin = Length > uHelloStr ? uHelloStr : Length;
uMin = strlen("这是一段来自内核空间的字符串");
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, "这是一段来自内核空间的字符串", uMin); //拷贝到缓冲区中给3环
status = STATUS_SUCCESS;
Length = strlen("这是一段来自内核空间的字符串");
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
Length = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
Length = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
NTSTATUS status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
ULONG Length;
KdPrint(("写操作\n"));
__try
{
Length = stack->Parameters.Write.Length;
if (Length>1)
{
KdPrint(("%s\n", Irp->AssociatedIrp.SystemBuffer));
status = STATUS_SUCCESS;
}
else
{
status = STATUS_INVALID_PARAMETER;
Length = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
Length = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
NTSTATUS DispatchQueryInfo(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
NTSTATUS status;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
ULONG Length;
KdPrint(("查操作\n"));
__try
{
Length = stack->Parameters.QueryFile.Length;
if (stack->Parameters.QueryFile.FileInformationClass == FileStandardInformation &&
Length>=sizeof(FILE_STANDARD_INFORMATION)
)
{
PFILE_STANDARD_INFORMATION pfsi = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
pfsi->EndOfFile.LowPart = 512 * 10;
status = STATUS_SUCCESS;
Length = sizeof(FILE_STANDARD_INFORMATION);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
Length = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
Length = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK");
UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
NTSTATUS status;
PDEVICE_OBJECT DeviceObject;
ULONG i = 0;
KdPrint(("Hello driver\n"));
DriverObject->DriverUnload = Unload;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
{
DriverObject->MajorFunction[i] = DispatchRoutine;
}
//读操作
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
//写操作
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
//查操作
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
//让设备对象知道驱动的位置
status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
if (!NT_SUCCESS(status))
{
KdPrint(("创建设备失败%x\n", status));
return status;
}
status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (!NT_SUCCESS(status))
{
KdPrint(("符号连接创建失败%x\n", status));
IoDeleteDevice(DeviceObject);
return status;
}
DeviceObject->Flags |= DO_BUFFERED_IO;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
应用层
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#define IOTEST CTL_CODE(FILE_DEVICE_UNKNOWN,0X800,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
HANDLE hDevice = CreateFile(TEXT("\\\\.\\HelloDDK"),
GENERIC_ALL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hDevice ==INVALID_HANDLE_VALUE)
{
printf("设备打开失败%d\n", GetLastError());
return -1;
}
DWORD dwRet;
CHAR Buffer[1024] = { 0 };
ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
printf("读回来的数据%s\n",Buffer);
printf("读取数据的个数%d\n", dwRet);
WriteFile(hDevice, "这是一段来自用户层的数据", strlen("这是一段来自用户层的数据"), &dwRet, NULL);
DWORD dwSize=GetFileSize(hDevice, NULL);
printf("文件长度%d\n", dwSize);
DeviceIoControl(hDevice, IOTEST, NULL, 0, NULL, 0, &dwRet, NULL);
CloseHandle(hDevice);
return 0;
}
高级篇(完整的读写操作)
内核层
#include <ntddk.h>
#include <windef.h>
typedef struct _DEVICE_EXTENSION
{
PCHAR Buffer;//内存首地址
ULONG Length;//文件长度
#define MAX_FILE_LEN 4096
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
IoDeleteSymbolicLink(&SymbolicLinkName);//删除连接
IoDeleteDevice(pDriverObject->DeviceObject);//释放驱动对象
//驱动卸载的时候显示
KdPrint(("Goodbye driver\n"));
}
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
static char* irpname[] = {
"IRP_MJ_CREATE ",
"IRP_MJ_CREATE_NAMED_PIPE ",
"IRP_MJ_CLOSE ",
"IRP_MJ_READ ",
"IRP_MJ_WRITE ",
"IRP_MJ_QUERY_INFORMATION ",
"IRP_MJ_SET_INFORMATION ",
"IRP_MJ_QUERY_EA ",
"IRP_MJ_SET_EA ",
"IRP_MJ_FLUSH_BUFFERS ",
"IRP_MJ_QUERY_VOLUME_INFORMATION",
"IRP_MJ_SET_VOLUME_INFORMATION ",
"IRP_MJ_DIRECTORY_CONTROL ",
"IRP_MJ_FILE_SYSTEM_CONTROL ",
"IRP_MJ_DEVICE_CONTROL ",
"IRP_MJ_INTERNAL_DEVICE_CONTROL ",
"IRP_MJ_SHUTDOWN ",
"IRP_MJ_LOCK_CONTROL ",
"IRP_MJ_CLEANUP ",
"IRP_MJ_CREATE_MAILSLOT ",
"IRP_MJ_QUERY_SECURITY ",
"IRP_MJ_SET_SECURITY ",
"IRP_MJ_POWER ",
"IRP_MJ_SYSTEM_CONTROL ",
"IRP_MJ_DEVICE_CHANGE ",
"IRP_MJ_QUERY_QUOTA ",
"IRP_MJ_SET_QUOTA ",
"IRP_MJ_PNP ",
"IRP_MJ_PNP_POWER ",
"IRP_MJ_MAXIMUM_FUNCTION "
};
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
KdPrint(("%s\n", irpname[stack->MajorFunction]));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;//设置返回状态,告诉操作是成功还是失败
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return STATUS_SUCCESS;
};
NTSTATUS DispatchRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
ULONG Length=0;
ULONG offset;
ULONG ReadLength;//读取到的实际长度
KdPrint(("读操作\n"));
__try
{
Length = stack->Parameters.Read.Length;
offset = stack->Parameters.Read.ByteOffset.LowPart;
if (Length + offset <= MAX_FILE_LEN)
{
if (Length + offset > pdx->Length)
{
//空间不足,实际能读取到的长度;
ReadLength = pdx->Length -offset;
}
else
{
ReadLength = Length;
}
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, pdx->Buffer+offset, ReadLength); //拷贝到缓冲区中给3环
status = STATUS_SUCCESS;
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
ReadLength = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
ReadLength = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = ReadLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
//首先不能超过内存块,在内存卡之内我写的文件长度,超过文件长度就需要更新文件长度,不超过文件长度保持不变
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
ULONG Length;
ULONG offset;
ULONG WriteLenth;//写出的实际长度
KdPrint(("写操作\n"));
__try
{
Length = stack->Parameters.Write.Length;
offset=stack->Parameters.Write.ByteOffset.LowPart;
if (Length+offset <= MAX_FILE_LEN)
{
if (Length+offset>pdx->Length)
{
//更新文件长度
pdx->Length = Length + offset;
}
RtlCopyMemory(pdx->Buffer+offset,Irp->AssociatedIrp.SystemBuffer,Length);
WriteLenth = Length;
}
else
{
status = STATUS_BUFFER_TOO_SMALL;//缓冲区太小的错误
WriteLenth = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
WriteLenth = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = WriteLenth;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
NTSTATUS DispatchQueryInfo(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
NTSTATUS status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
ULONG Length;
KdPrint(("查操作\n"));
__try
{
Length = stack->Parameters.QueryFile.Length;
if (stack->Parameters.QueryFile.FileInformationClass == FileStandardInformation &&
Length>=sizeof(FILE_STANDARD_INFORMATION)
)
{
PFILE_STANDARD_INFORMATION pfsi = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
pfsi->EndOfFile.LowPart = pdx->Length;
status = STATUS_SUCCESS;
Length = sizeof(FILE_STANDARD_INFORMATION);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
Length = 0;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
Length = 0;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
return status;
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK");
UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
NTSTATUS status;
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION pdx;
ULONG i = 0;
KdPrint(("Hello driver\n"));
DriverObject->DriverUnload = Unload;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
{
DriverObject->MajorFunction[i] = DispatchRoutine;
}
//读操作
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
//写操作
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
//查操作
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
//让设备对象知道驱动的位置
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
if (!NT_SUCCESS(status))
{
KdPrint(("创建设备失败%x\n", status));
return status;
}
status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (!NT_SUCCESS(status))
{
KdPrint(("符号连接创建失败%x\n", status));
IoDeleteDevice(DeviceObject);
return status;
}
DeviceObject->Flags |= DO_BUFFERED_IO;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
pdx = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
pdx->Buffer = (PCHAR)ExAllocatePoolWithTag(PagedPool, 4096, 'a');
pdx->Length = 0;
return STATUS_SUCCESS;
}
应用层
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#define IOTEST CTL_CODE(FILE_DEVICE_UNKNOWN,0X800,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
HANDLE hDevice = CreateFile(TEXT("\\\\.\\HelloDDK"),
GENERIC_ALL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hDevice ==INVALID_HANDLE_VALUE)
{
printf("设备打开失败%d\n", GetLastError());
return -1;
}
DWORD dwRet;
CHAR Buffer[1024] = { 0 };
WriteFile(hDevice, "这是一段来自用户层的数据", strlen("这是一段来自用户层的数据"), &dwRet, NULL);
ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
printf("读回来的数据%s\n",Buffer);
printf("读取数据的个数%d\n", dwRet);
DWORD dwSize=GetFileSize(hDevice, NULL);
printf("文件长度%d\n", dwSize);
DeviceIoControl(hDevice, IOTEST, NULL, 0, NULL, 0, &dwRet, NULL);
CloseHandle(hDevice);
return 0;
}