我研究filedisk的一些注解,有哪里不对,请高人指教下
//filedisk.h文件内容
#ifndef _FILE_DISK_
#define _FILE_DISK_
#ifndef __T
#ifdef _NTDDK_
#define __T(x) L ## x
#else
#define __T(x) x
#endif
#endif
#ifndef _T
#define _T(x) __T(x)
#endif
#define DEVICE_BASE_NAME _T("//FileDisk")
#define DEVICE_DIR_NAME _T("//Device") DEVICE_BASE_NAME
#define DEVICE_NAME_PREFIX DEVICE_DIR_NAME DEVICE_BASE_NAME
//用户自定义IRP消息,地址范围0x8000-0xffff
#define FILE_DEVICE_FILE_DISK 0x8000
#define IOCTL_FILE_DISK_OPEN_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x800, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_FILE_DISK_CLOSE_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x801, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_FILE_DISK_QUERY_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x802, METHOD_BUFFERED,
FILE_READ_ACCESS)
typedef struct _OPEN_FILE_INFORMATION {
LARGE_INTEGER FileSize;
BOOLEAN ReadOnly;
USHORT FileNameLength;
UCHAR FileName[1];
} OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;
#endif
/******************************************************************/
//filedisk.c文件内容
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntverp.h>
#if (VER_PRODUCTBUILD < 2195)
#define FILE_DEVICE_MASS_STORAGE 0x0000002d
#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
#endif
#if (VER_PRODUCTBUILD < 2600)
//IOCTL的合并宏
#define IOCTL_DISK_GET_PARTITION_INFO_EX CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)
typedef enum _PARTITION_STYLE {
PARTITION_STYLE_MBR,
PARTITION_STYLE_GPT
} PARTITION_STYLE;
typedef unsigned __int64 ULONG64, *PULONG64;
//MBR结构体
typedef struct _PARTITION_INFORMATION_MBR {
UCHAR PartitionType;
BOOLEAN BootIndicator;
BOOLEAN RecognizedPartition;
ULONG HiddenSectors;
} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR;
//分区参数表
typedef struct _PARTITION_INFORMATION_GPT {
GUID PartitionType;
GUID PartitionId;
ULONG64 Attributes;
WCHAR Name[36];
} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT;
typedef struct _PARTITION_INFORMATION_EX {
PARTITION_STYLE PartitionStyle;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER PartitionLength;
ULONG PartitionNumber;
BOOLEAN RewritePartition;
union {
PARTITION_INFORMATION_MBR Mbr;
PARTITION_INFORMATION_GPT Gpt;
};
} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX;
typedef struct _GET_LENGTH_INFORMATION {
LARGE_INTEGER Length;
} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION;
#endif // (VER_PRODUCTBUILD < 2600)
//
// We include some stuff from ntifs.h here so that
// the driver can be compiled with only the DDK.
//
#define TOKEN_SOURCE_LENGTH 8
typedef enum _TOKEN_TYPE {
TokenPrimary = 1,
TokenImpersonation
} TOKEN_TYPE;
typedef struct _TOKEN_SOURCE {
CCHAR SourceName[TOKEN_SOURCE_LENGTH];
LUID SourceIdentifier;
} TOKEN_SOURCE, *PTOKEN_SOURCE;
typedef struct _TOKEN_CONTROL {
LUID TokenId;
LUID AuthenticationId;
LUID ModifiedId;
TOKEN_SOURCE TokenSource;
} TOKEN_CONTROL, *PTOKEN_CONTROL;
//受保护内容结构体
typedef struct _SECURITY_CLIENT_CONTEXT {
SECURITY_QUALITY_OF_SERVICE SecurityQos;
PACCESS_TOKEN ClientToken;
BOOLEAN DirectlyAccessClientToken;
BOOLEAN DirectAccessEffectiveOnly;
BOOLEAN ServerIsRemote;
TOKEN_CONTROL ClientTokenControl;
} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT;
#define PsDereferenceImpersonationToken(T) /
{if (ARGUMENT_PRESENT(T)) { /
(ObDereferenceObject((T))); /
} else { /
; /
} /
}
#define PsDereferencePrimaryToken(T) (ObDereferenceObject((T)))
NTKERNELAPI
VOID
PsRevertToSelf (
VOID
);
//引用ntoskrnl.exe的内核函数
NTKERNELAPI
NTSTATUS
SeCreateClientSecurity (
IN PETHREAD Thread,
IN PSECURITY_QUALITY_OF_SERVICE QualityOfService,
IN BOOLEAN RemoteClient,
OUT PSECURITY_CLIENT_CONTEXT ClientContext
);
#define SeDeleteClientSecurity(C) { /
if (SeTokenType((C)->ClientToken) == TokenPrimary) { /
PsDereferencePrimaryToken( (C)->ClientToken ); /
} else { /
PsDereferenceImpersonationToken( (C)->ClientToken ); /
} /
}
NTKERNELAPI
VOID
SeImpersonateClient (
IN PSECURITY_CLIENT_CONTEXT ClientContext,
IN PETHREAD ServerThread OPTIONAL
);
NTKERNELAPI
TOKEN_TYPE
SeTokenType (
IN PACCESS_TOKEN Token
);
//
// For backward compatibility with Windows NT 4.0 by Bruce Engle.
//
#ifndef MmGetSystemAddressForMdlSafe
#define MmGetSystemAddressForMdlSafe(MDL, PRIORITY) MmGetSystemAddressForMdlPrettySafe(MDL)
PVOID
MmGetSystemAddressForMdlPrettySafe (
PMDL Mdl
)
{
CSHORT MdlMappingCanFail;
PVOID MappedSystemVa;
MdlMappingCanFail = Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;
Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
MappedSystemVa = MmGetSystemAddressForMdl(Mdl);
if (MdlMappingCanFail == 0)
{
Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
}
return MappedSystemVa;
}
#endif
#include "filedisk.h"
#define PARAMETER_KEY L"//Parameters"
#define NUMBEROFDEVICES_VALUE L"NumberOfDevices"
#define DEFAULT_NUMBEROFDEVICES 4
#define SECTOR_SIZE 512
#define TOC_DATA_TRACK 0x04
HANDLE dir_handle;
typedef struct _DEVICE_EXTENSION {
BOOLEAN media_in_device;
HANDLE file_handle;
ANSI_STRING file_name;
LARGE_INTEGER file_size;
BOOLEAN read_only;
PSECURITY_CLIENT_CONTEXT security_client_context;
LIST_ENTRY list_head;
KSPIN_LOCK list_lock;
KEVENT request_event;
PVOID thread_pointer;
BOOLEAN terminate_thread;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number,
IN DEVICE_TYPE DeviceType
);
VOID
FileDiskUnload (
IN PDRIVER_OBJECT DriverObject
);
PDEVICE_OBJECT
FileDiskDeleteDevice (
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
FileDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskReadWrite (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
FileDiskThread (
IN PVOID Context
);
NTSTATUS
FileDiskOpenFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskCloseFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
int swprintf(wchar_t *, const wchar_t *, ...);
#pragma code_seg("INIT")
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
UNICODE_STRING parameter_path;
RTL_QUERY_REGISTRY_TABLE query_table[2]; //注册表查询返回值
ULONG n_devices;
NTSTATUS status;
UNICODE_STRING device_dir_name;
OBJECT_ATTRIBUTES object_attributes;
ULONG n;
USHORT n_created_devices;
parameter_path.Length = 0;
parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY); //获取绝对路径的长度
parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength); //分配UNICODE_STRING的缓存
if (parameter_path.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(¶meter_path, RegistryPath);
RtlAppendUnicodeToString(¶meter_path, PARAMETER_KEY); //合并为完整路径HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/FileDisk/Parameters
RtlZeroMemory(&query_table[0], sizeof(query_table)); //变量空间填0初始化
query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
query_table[0].Name = NUMBEROFDEVICES_VALUE;
query_table[0].EntryContext = &n_devices;
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
parameter_path.Buffer,
&query_table[0],
NULL,
NULL
);
ExFreePool(parameter_path.Buffer);
if (!NT_SUCCESS(status)) //读取注册表信息来确定安装多少个驱动线程
{
KdPrint(("FileDisk: Query registry failed, using default values./n"));
n_devices = DEFAULT_NUMBEROFDEVICES;
}
RtlInitUnicodeString(&device_dir_name, DEVICE_DIR_NAME); //在.h头文件定义为"//Device//filedisk"
//获取驱动属性,为下面的zwCreatexxx准备
InitializeObjectAttributes(
&object_attributes,
&device_dir_name,
OBJ_PERMANENT,
NULL,
NULL
);
status = ZwCreateDirectoryObject(
&dir_handle,
DIRECTORY_ALL_ACCESS,
&object_attributes
); //SDK下CreateDirectoryObject的边种,所有zwCreateFile,zwOpenKey,zwWriteFile都是win32 API的翻版
if (!NT_SUCCESS(status))
{
return status;
}
ZwMakeTemporaryObject(dir_handle);//创建临时档
for (n = 0, n_created_devices = 0; n < n_devices; n++) //n_devices由上面的注册表读取获得
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_DISK); //挂载磁盘驱动器,载FILE_DEVICE在ntddk.h里,在DDK手册的Specifying Device Types专题
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
for (n = 0; n < n_devices; n++)
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_CD_ROM); //挂载CD驱动器
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
if (n_created_devices == 0)
{
ZwClose(dir_handle);
return status;
}
//filedisk过滤器的IRP消息->处理函数映射
DriverObject->MajorFunction[IRP_MJ_CREATE] = FileDiskCreateClose;//响应建立关闭
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FileDiskReadWrite;//响应一般读写
DriverObject->MajorFunction[IRP_MJ_WRITE] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl; //设置IRP控制函数
//设置卸载规则
DriverObject->DriverUnload = FileDiskUnload;
return STATUS_SUCCESS;
}
//创建虚拟设备的子函数,整个虚拟驱动的关键,输入参数: (PDO对象,驱动器序列数,驱动类型)
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number,
IN DEVICE_TYPE DeviceType
)
{
WCHAR device_name_buffer[MAXIMUM_FILENAME_LENGTH];
UNICODE_STRING device_name;
NTSTATUS status;
PDEVICE_OBJECT device_object; //新建的虚拟设备PDO
PDEVICE_EXTENSION device_extension;
HANDLE thread_handle;//新建线程的操作句柄
ASSERT(DriverObject != NULL); //对象不存在,抛出debug异常;
//格式化虚拟设备名,UNICODE标准
if (DeviceType == FILE_DEVICE_CD_ROM)
{
swprintf(
device_name_buffer,
DEVICE_NAME_PREFIX L"Cd" L"%u", //L"字符串串"为字符串合并
Number
);
}
else
{
swprintf(
device_name_buffer,
DEVICE_NAME_PREFIX L"%u",
Number
);
}
RtlInitUnicodeString(&device_name, device_name_buffer);
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION), //分配磁盘空间
&device_name, //设定新驱动名字
DeviceType, //参数入口的DeviceType传递到这里了
0,
FALSE, //支持overlapped I/O多线程操作
&device_object
);
if (!NT_SUCCESS(status))
{
return status;
}
device_object->Flags |= DO_DIRECT_IO; //初始化的通常动作,这种模式需要为IRP_MJ_WRITE和IRP_MJ_READ请求创建MDL空间,那是一个系统全局缓冲区
//设备扩展结构,用来维护一些常规性操作,此结构为自定义结构
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
device_extension->media_in_device = FALSE;
if (DeviceType == FILE_DEVICE_CD_ROM)
{
device_object->Characteristics |= FILE_READ_ONLY_DEVICE; //如果是CD-ROM的话就设定为只读
device_extension->read_only = TRUE;
}
if (DeviceType == FILE_DEVICE_SMARTCARD)
{
device_object->Characteristics = FILE_REMOVABLE_MEDIA; //如果是磁盘的话就设定为移动媒体
device_extension->read_only = TRUE;
}
if (DeviceType == FILE_DEVICE_DISK)
{
device_object->Characteristics = FILE_REMOVABLE_MEDIA; //如果是磁盘的话就设定为移动媒体
device_extension->read_only = TRUE;
}
//为IRP消息而设的双向循环链表结构
InitializeListHead(&device_extension->list_head);
//自旋锁初始化,锁住双向链表,在线程处理中解锁
KeInitializeSpinLock(&device_extension->list_lock);
//设置同步事件
KeInitializeEvent(
&device_extension->request_event,
SynchronizationEvent, //同步事件操作,在每一次wait通过后自动将事件设为未受信状态,使下一次wait阻塞.NotificationEvent则不会自动设置,需要手动
FALSE //初始状态为未受信状态
);
//设置线程有效
device_extension->terminate_thread = FALSE;
//建立主线程,实际上一个盘只有一个线程操作
status = PsCreateSystemThread(
&thread_handle, //获得线程句柄
(ACCESS_MASK) 0L, //屏蔽消息
NULL,
NULL,
NULL,
FileDiskThread, //触发磁盘操作线程
device_object
);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(device_object);
return status;
}
//返回线程真实地址并保存到thread_pointer
status = ObReferenceObjectByHandle(
thread_handle,
THREAD_ALL_ACCESS,
NULL,
KernelMode, //消息类型为核心态模式
&device_extension->thread_pointer,
NULL
);
if (!NT_SUCCESS(status))
{
ZwClose(thread_handle);//释放线程建立时的操作句柄
//结束线程标志置位,结束线程
device_extension->terminate_thread = TRUE;
//触发事件结束线程
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0, //当事件受信触发下一步操作时,设置事件优先级提高的递增量
FALSE//Wait等待通过后自动设回未受信状态
);
//删除对象
IoDeleteDevice(device_object);
return status;
}
ZwClose(thread_handle);
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
//驱动卸载响应
VOID
FileDiskUnload (
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT device_object;
PAGED_CODE();
device_object = DriverObject->DeviceObject;
while (device_object)
{
device_object = FileDiskDeleteDevice(device_object);//此函数返回下一PDO对象,通过循环释放所有PDO
}
ZwClose(dir_handle);
}
PDEVICE_OBJECT
FileDiskDeleteDevice (
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION device_extension;
PDEVICE_OBJECT next_device_object;
PAGED_CODE();//保证 IRQL <= DISPATCH_LEVEL
ASSERT(DeviceObject != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//结束线程标志
device_extension->terminate_thread = TRUE;
//使事件受信,触发一次线程操作以结束线程
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
KeWaitForSingleObject(
device_extension->thread_pointer,
Executive,
KernelMode,
FALSE,
NULL
);
//通知扩展的操作释放
ObDereferenceObject(device_extension->thread_pointer);
//释放安全描述字
if (device_extension->security_client_context != NULL)
{
SeDeleteClientSecurity(device_extension->security_client_context);
ExFreePool(device_extension->security_client_context);
}
next_device_object = DeviceObject->NextDevice;
IoDeleteDevice(DeviceObject);
//返回下一个设备的指针
return next_device_object;
}
NTSTATUS
FileDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PAGED_CODE();
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
//完成响应,若IRPL>DISPATCH_LEVEL则会使调用程序处于等待状态,
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
#pragma code_seg()
NTSTATUS
FileDiskReadWrite (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PIO_STACK_LOCATION io_stack;
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
if (!device_extension->media_in_device)//虚拟盘内没介质则出错
{
Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEDIA_IN_DEVICE;
}
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (io_stack->Parameters.Read.Length == 0)//如果没数据,直接返回
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//标识IRP已经处理
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//返回成功
return STATUS_SUCCESS;
}
//通知客户端等IRP_MJ_READ/WRITE的响应
IoMarkIrpPending(Irp);
//插入到Irq处理队列链头
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
//触发线程事件
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
//返回等待处理响应
return STATUS_PENDING;
}
//IRP信息处理
NTSTATUS
FileDiskDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PIO_STACK_LOCATION io_stack;
NTSTATUS status;
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (!device_extension->media_in_device &&
io_stack->Parameters.DeviceIoControl.IoControlCode !=
IOCTL_FILE_DISK_OPEN_FILE)
{//监测到没介质,返回提示
Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEDIA_IN_DEVICE;
}
switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_FILE_DISK_OPEN_FILE:
{
SECURITY_QUALITY_OF_SERVICE security_quality_of_service;
if (device_extension->media_in_device)
{
KdPrint(("FileDisk: IOCTL_FILE_DISK_OPEN_FILE: Media already opened/n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(OPEN_FILE_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(OPEN_FILE_INFORMATION) +
((POPEN_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->FileNameLength -
sizeof(UCHAR))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
if (device_extension->security_client_context != NULL)
{ //区域保护
SeDeleteClientSecurity(device_extension->security_client_context);
}
else
{ //设置保护区域
device_extension->security_client_context =
ExAllocatePool(NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT));
}
RtlZeroMemory(&security_quality_of_service, sizeof(SECURITY_QUALITY_OF_SERVICE));
security_quality_of_service.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
security_quality_of_service.ImpersonationLevel = SecurityImpersonation;
security_quality_of_service.ContextTrackingMode = SECURITY_STATIC_TRACKING;
security_quality_of_service.EffectiveOnly = FALSE;
SeCreateClientSecurity(
PsGetCurrentThread(),
&security_quality_of_service,
FALSE,
device_extension->security_client_context
);
//设置IRP等待,通过主线程处理
IoMarkIrpPending(Irp);
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
status = STATUS_PENDING;
break;
}
case IOCTL_FILE_DISK_CLOSE_FILE:
{//通过主线程处理
IoMarkIrpPending(Irp);
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
status = STATUS_PENDING;
break;
}
case IOCTL_FILE_DISK_QUERY_FILE:
{
POPEN_FILE_INFORMATION open_file_information;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(OPEN_FILE_INFORMATION) + device_extension->file_name.Length - sizeof(UCHAR))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
open_file_information->FileSize.QuadPart = device_extension->file_size.QuadPart;
open_file_information->ReadOnly = device_extension->read_only;
open_file_information->FileNameLength = device_extension->file_name.Length;
RtlCopyMemory(
open_file_information->FileName,
device_extension->file_name.Buffer,
device_extension->file_name.Length
);
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(OPEN_FILE_INFORMATION) +
open_file_information->FileNameLength - sizeof(UCHAR);
break;
}
case IOCTL_DISK_CHECK_VERIFY:
case IOCTL_CDROM_CHECK_VERIFY:
case IOCTL_STORAGE_CHECK_VERIFY:
case IOCTL_STORAGE_CHECK_VERIFY2:
{ //默认处理
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
{//物理参数处理
PDISK_GEOMETRY disk_geometry;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_GEOMETRY))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
disk_geometry->Cylinders.QuadPart = length / SECTOR_SIZE / 32 / 2;
disk_geometry->MediaType = FixedMedia;
disk_geometry->TracksPerCylinder = 2;
disk_geometry->SectorsPerTrack = 32;
disk_geometry->BytesPerSector = SECTOR_SIZE;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
break;
}
case IOCTL_DISK_GET_LENGTH_INFO:
{
PGET_LENGTH_INFORMATION get_length_information;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GET_LENGTH_INFORMATION))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
get_length_information = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
get_length_information->Length.QuadPart = device_extension->file_size.QuadPart;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
break;
}
case IOCTL_DISK_GET_PARTITION_INFO:
{//获取分区信息
PPARTITION_INFORMATION partition_information;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
partition_information->StartingOffset.QuadPart = 0;
partition_information->PartitionLength.QuadPart = length;
partition_information->HiddenSectors = 1;
partition_information->PartitionNumber = 0;
partition_information->PartitionType = 0;
partition_information->BootIndicator = FALSE;
partition_information->RecognizedPartition = FALSE;
partition_information->RewritePartition = FALSE;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
break;
}
//分区表额外信息
case IOCTL_DISK_GET_PARTITION_INFO_EX:
{
PPARTITION_INFORMATION_EX partition_information_ex;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION_EX))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information_ex = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
partition_information_ex->PartitionStyle = PARTITION_STYLE_MBR;
partition_information_ex->StartingOffset.QuadPart = 0;
partition_information_ex->PartitionLength.QuadPart = length;
partition_information_ex->PartitionNumber = 0;
partition_information_ex->RewritePartition = FALSE;
partition_information_ex->Mbr.PartitionType = 0;
partition_information_ex->Mbr.BootIndicator = FALSE;
partition_information_ex->Mbr.RecognizedPartition = FALSE;
partition_information_ex->Mbr.HiddenSectors = 1;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
break;
}
//设备是否可写
case IOCTL_DISK_IS_WRITABLE:
{
if (!device_extension->read_only)
{
status = STATUS_SUCCESS;
}
else
{
status = STATUS_MEDIA_WRITE_PROTECTED;
}
Irp->IoStatus.Information = 0;
break;
}
//设施是否可移动
case IOCTL_DISK_MEDIA_REMOVAL:
case IOCTL_STORAGE_MEDIA_REMOVAL:
{
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_CDROM_READ_TOC:
{
PCDROM_TOC cdrom_toc;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(CDROM_TOC))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
cdrom_toc = (PCDROM_TOC) Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(cdrom_toc, sizeof(CDROM_TOC));
cdrom_toc->FirstTrack = 1;
cdrom_toc->LastTrack = 1;
cdrom_toc->TrackData[0].Control = TOC_DATA_TRACK;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(CDROM_TOC);
break;
}
case IOCTL_DISK_SET_PARTITION_INFO:
{
if (device_extension->read_only)
{
status = STATUS_MEDIA_WRITE_PROTECTED;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SET_PARTITION_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_DISK_VERIFY:
{//磁盘检验
PVERIFY_INFORMATION verify_information;
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(VERIFY_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = verify_information->Length;
break;
}
default:
{//默认处理
KdPrint((
"FileDisk: Unknown IoControlCode %#x/n",
io_stack->Parameters.DeviceIoControl.IoControlCode
));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
}
}
if (status != STATUS_PENDING)
{
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
//操作处理线程,输入参数(空指针化的PDO),此线程由FileDiskDeviceDevice调用,在驱动被调用时启动,完成初始化操作.
VOID
FileDiskThread (
IN PVOID Context
)
{
PDEVICE_OBJECT device_object;
PDEVICE_EXTENSION device_extension;
PLIST_ENTRY request; //双向链表的IRP栈
PIRP irp;
PIO_STACK_LOCATION io_stack;
PUCHAR system_buffer;
PUCHAR buffer;
ASSERT(Context != NULL);
device_object = (PDEVICE_OBJECT) Context;
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
//设置优先级
KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
for (;;)//以下为线程的无限循环,当device_extension->terminate_thread设为true时才结束.
{
//等待request_event事件置信,for每循环一次,在这里被阻塞,等待
KeWaitForSingleObject(
&device_extension->request_event,
Executive,
KernelMode,
FALSE,
NULL
);
//如果结束线程标志置位,结束线程
if (device_extension->terminate_thread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
}
//遍历IRP表
while (request = ExInterlockedRemoveHeadList(
&device_extension->list_head,
&device_extension->list_lock
)) //list不为空,则指向下一链表数据
{
irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry); //获取irp基地址,tail是IRP结构里面的一个Union结构,Tail.Overlay.ListEntry说明IRP入栈待处理
IRP的栈返回形式
io_stack = IoGetCurrentIrpStackLocation(irp);
switch (io_stack->MajorFunction)
{
case IRP_MJ_READ://读数据到内存
system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);//分配MDL虚拟地址空间
if (system_buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;//分配失败返回资源不足警告
irp->IoStatus.Information = 0;
break;
}
buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length); //分配空间
if (buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
ZwReadFile(
device_extension->file_handle, //读取指定的映像文件
NULL,
NULL,
NULL,
&irp->IoStatus,
buffer, //文件缓冲
io_stack->Parameters.Read.Length,
&io_stack->Parameters.Read.ByteOffset,
NULL
);
RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length); //将文件缓冲读入到MDL缓冲
ExFreePool(buffer);//释放文件缓冲
break;
case IRP_MJ_WRITE://内存数据写到设备
if ((io_stack->Parameters.Write.ByteOffset.QuadPart +
io_stack->Parameters.Write.Length) >
device_extension->file_size.QuadPart)//判错处理
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
irp->IoStatus.Information = 0;
}
ZwWriteFile(
device_extension->file_handle,
NULL,
NULL,
NULL,
&irp->IoStatus,
MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), //从MDL缓冲写入文件
io_stack->Parameters.Write.Length,
&io_stack->Parameters.Write.ByteOffset,
NULL
); //写文件
break;
//下面的是自定义IRP响应
case IRP_MJ_DEVICE_CONTROL:
switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_FILE_DISK_OPEN_FILE:
//nt未公开函数,应该是权限设置
SeImpersonateClient(device_extension->security_client_context, NULL);
irp->IoStatus.Status = FileDiskOpenFile(device_object, irp);
PsRevertToSelf();//nt未公开函数
break;
case IOCTL_FILE_DISK_CLOSE_FILE:
irp->IoStatus.Status = FileDiskCloseFile(device_object, irp);
break;
default:
irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
}
break;
default:
irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
}
IoCompleteRequest(
irp,
(CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?
IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
}
}
}
#pragma code_seg("PAGE")
//打开映像文件相关操作
NTSTATUS
FileDiskOpenFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
POPEN_FILE_INFORMATION open_file_information;
UNICODE_STRING ufile_name;
NTSTATUS status;
OBJECT_ATTRIBUTES object_attributes;
FILE_END_OF_FILE_INFORMATION file_eof;
FILE_BASIC_INFORMATION file_basic;
FILE_STANDARD_INFORMATION file_standard;
FILE_ALIGNMENT_INFORMATION file_alignment;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//从Irq用户提交的buffer中获取文件信息
open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
{
device_extension->read_only = open_file_information->ReadOnly;
}
//获取文件名
device_extension->file_name.Length = open_file_information->FileNameLength;
device_extension->file_name.MaximumLength = open_file_information->FileNameLength;
device_extension->file_name.Buffer = ExAllocatePool(NonPagedPool, open_file_information->FileNameLength);
RtlCopyMemory(
device_extension->file_name.Buffer,
open_file_information->FileName,
open_file_information->FileNameLength
);
status = RtlAnsiStringToUnicodeString(
&ufile_name, //转换成UNICODE路径
&device_extension->file_name,
TRUE
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
return status;
}
InitializeObjectAttributes(
&object_attributes,
&ufile_name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = ZwCreateFile( //打开映像文件
&device_extension->file_handle,
device_extension->read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&Irp->IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
device_extension->read_only ? FILE_SHARE_READ : 0,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NO_SUCH_FILE)
{
if (device_extension->read_only || open_file_information->FileSize.QuadPart == 0)
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
Irp->IoStatus.Status = STATUS_NO_SUCH_FILE;
Irp->IoStatus.Information = 0;
return STATUS_NO_SUCH_FILE;
}
else
{
status = ZwCreateFile(
&device_extension->file_handle,
GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&Irp->IoStatus,
&open_file_information->FileSize,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,//如果文件存在则打开,不存在建立
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
return status;
}
if (Irp->IoStatus.Information == FILE_CREATED)
{
file_eof.EndOfFile.QuadPart = open_file_information->FileSize.QuadPart;
status = ZwSetInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_eof,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation
);
if (!NT_SUCCESS(status))
{//释放临时量
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
ZwClose(device_extension->file_handle);
return status;
}
}
}
}
else if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
return status;
}
RtlFreeUnicodeString(&ufile_name);
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_basic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_standard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
device_extension->file_size.QuadPart = file_standard.EndOfFile.QuadPart;
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_alignment,
sizeof(FILE_ALIGNMENT_INFORMATION),
FileAlignmentInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
DeviceObject->AlignmentRequirement = file_alignment.AlignmentRequirement;
if (device_extension->read_only)
{
DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
}
else
{
DeviceObject->Characteristics &= ~FILE_READ_ONLY_DEVICE;
}
device_extension->media_in_device = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
//映像文件关闭并释放资源函数
NTSTATUS
FileDiskCloseFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
device_extension->media_in_device = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
//filedisk.h文件内容
#ifndef _FILE_DISK_
#define _FILE_DISK_
#ifndef __T
#ifdef _NTDDK_
#define __T(x) L ## x
#else
#define __T(x) x
#endif
#endif
#ifndef _T
#define _T(x) __T(x)
#endif
#define DEVICE_BASE_NAME _T("//FileDisk")
#define DEVICE_DIR_NAME _T("//Device") DEVICE_BASE_NAME
#define DEVICE_NAME_PREFIX DEVICE_DIR_NAME DEVICE_BASE_NAME
//用户自定义IRP消息,地址范围0x8000-0xffff
#define FILE_DEVICE_FILE_DISK 0x8000
#define IOCTL_FILE_DISK_OPEN_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x800, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_FILE_DISK_CLOSE_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x801, METHOD_BUFFERED,
FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_FILE_DISK_QUERY_FILE CTL_CODE(FILE_DEVICE_FILE_DISK, 0x802, METHOD_BUFFERED,
FILE_READ_ACCESS)
typedef struct _OPEN_FILE_INFORMATION {
LARGE_INTEGER FileSize;
BOOLEAN ReadOnly;
USHORT FileNameLength;
UCHAR FileName[1];
} OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;
#endif
/******************************************************************/
//filedisk.c文件内容
#include <ntddk.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <ntverp.h>
#if (VER_PRODUCTBUILD < 2195)
#define FILE_DEVICE_MASS_STORAGE 0x0000002d
#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
#endif
#if (VER_PRODUCTBUILD < 2600)
//IOCTL的合并宏
#define IOCTL_DISK_GET_PARTITION_INFO_EX CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)
typedef enum _PARTITION_STYLE {
PARTITION_STYLE_MBR,
PARTITION_STYLE_GPT
} PARTITION_STYLE;
typedef unsigned __int64 ULONG64, *PULONG64;
//MBR结构体
typedef struct _PARTITION_INFORMATION_MBR {
UCHAR PartitionType;
BOOLEAN BootIndicator;
BOOLEAN RecognizedPartition;
ULONG HiddenSectors;
} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR;
//分区参数表
typedef struct _PARTITION_INFORMATION_GPT {
GUID PartitionType;
GUID PartitionId;
ULONG64 Attributes;
WCHAR Name[36];
} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT;
typedef struct _PARTITION_INFORMATION_EX {
PARTITION_STYLE PartitionStyle;
LARGE_INTEGER StartingOffset;
LARGE_INTEGER PartitionLength;
ULONG PartitionNumber;
BOOLEAN RewritePartition;
union {
PARTITION_INFORMATION_MBR Mbr;
PARTITION_INFORMATION_GPT Gpt;
};
} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX;
typedef struct _GET_LENGTH_INFORMATION {
LARGE_INTEGER Length;
} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION;
#endif // (VER_PRODUCTBUILD < 2600)
//
// We include some stuff from ntifs.h here so that
// the driver can be compiled with only the DDK.
//
#define TOKEN_SOURCE_LENGTH 8
typedef enum _TOKEN_TYPE {
TokenPrimary = 1,
TokenImpersonation
} TOKEN_TYPE;
typedef struct _TOKEN_SOURCE {
CCHAR SourceName[TOKEN_SOURCE_LENGTH];
LUID SourceIdentifier;
} TOKEN_SOURCE, *PTOKEN_SOURCE;
typedef struct _TOKEN_CONTROL {
LUID TokenId;
LUID AuthenticationId;
LUID ModifiedId;
TOKEN_SOURCE TokenSource;
} TOKEN_CONTROL, *PTOKEN_CONTROL;
//受保护内容结构体
typedef struct _SECURITY_CLIENT_CONTEXT {
SECURITY_QUALITY_OF_SERVICE SecurityQos;
PACCESS_TOKEN ClientToken;
BOOLEAN DirectlyAccessClientToken;
BOOLEAN DirectAccessEffectiveOnly;
BOOLEAN ServerIsRemote;
TOKEN_CONTROL ClientTokenControl;
} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT;
#define PsDereferenceImpersonationToken(T) /
{if (ARGUMENT_PRESENT(T)) { /
(ObDereferenceObject((T))); /
} else { /
; /
} /
}
#define PsDereferencePrimaryToken(T) (ObDereferenceObject((T)))
NTKERNELAPI
VOID
PsRevertToSelf (
VOID
);
//引用ntoskrnl.exe的内核函数
NTKERNELAPI
NTSTATUS
SeCreateClientSecurity (
IN PETHREAD Thread,
IN PSECURITY_QUALITY_OF_SERVICE QualityOfService,
IN BOOLEAN RemoteClient,
OUT PSECURITY_CLIENT_CONTEXT ClientContext
);
#define SeDeleteClientSecurity(C) { /
if (SeTokenType((C)->ClientToken) == TokenPrimary) { /
PsDereferencePrimaryToken( (C)->ClientToken ); /
} else { /
PsDereferenceImpersonationToken( (C)->ClientToken ); /
} /
}
NTKERNELAPI
VOID
SeImpersonateClient (
IN PSECURITY_CLIENT_CONTEXT ClientContext,
IN PETHREAD ServerThread OPTIONAL
);
NTKERNELAPI
TOKEN_TYPE
SeTokenType (
IN PACCESS_TOKEN Token
);
//
// For backward compatibility with Windows NT 4.0 by Bruce Engle.
//
#ifndef MmGetSystemAddressForMdlSafe
#define MmGetSystemAddressForMdlSafe(MDL, PRIORITY) MmGetSystemAddressForMdlPrettySafe(MDL)
PVOID
MmGetSystemAddressForMdlPrettySafe (
PMDL Mdl
)
{
CSHORT MdlMappingCanFail;
PVOID MappedSystemVa;
MdlMappingCanFail = Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;
Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
MappedSystemVa = MmGetSystemAddressForMdl(Mdl);
if (MdlMappingCanFail == 0)
{
Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
}
return MappedSystemVa;
}
#endif
#include "filedisk.h"
#define PARAMETER_KEY L"//Parameters"
#define NUMBEROFDEVICES_VALUE L"NumberOfDevices"
#define DEFAULT_NUMBEROFDEVICES 4
#define SECTOR_SIZE 512
#define TOC_DATA_TRACK 0x04
HANDLE dir_handle;
typedef struct _DEVICE_EXTENSION {
BOOLEAN media_in_device;
HANDLE file_handle;
ANSI_STRING file_name;
LARGE_INTEGER file_size;
BOOLEAN read_only;
PSECURITY_CLIENT_CONTEXT security_client_context;
LIST_ENTRY list_head;
KSPIN_LOCK list_lock;
KEVENT request_event;
PVOID thread_pointer;
BOOLEAN terminate_thread;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number,
IN DEVICE_TYPE DeviceType
);
VOID
FileDiskUnload (
IN PDRIVER_OBJECT DriverObject
);
PDEVICE_OBJECT
FileDiskDeleteDevice (
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
FileDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskReadWrite (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
FileDiskThread (
IN PVOID Context
);
NTSTATUS
FileDiskOpenFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
FileDiskCloseFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
int swprintf(wchar_t *, const wchar_t *, ...);
#pragma code_seg("INIT")
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
UNICODE_STRING parameter_path;
RTL_QUERY_REGISTRY_TABLE query_table[2]; //注册表查询返回值
ULONG n_devices;
NTSTATUS status;
UNICODE_STRING device_dir_name;
OBJECT_ATTRIBUTES object_attributes;
ULONG n;
USHORT n_created_devices;
parameter_path.Length = 0;
parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY); //获取绝对路径的长度
parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength); //分配UNICODE_STRING的缓存
if (parameter_path.Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(¶meter_path, RegistryPath);
RtlAppendUnicodeToString(¶meter_path, PARAMETER_KEY); //合并为完整路径HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/FileDisk/Parameters
RtlZeroMemory(&query_table[0], sizeof(query_table)); //变量空间填0初始化
query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
query_table[0].Name = NUMBEROFDEVICES_VALUE;
query_table[0].EntryContext = &n_devices;
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
parameter_path.Buffer,
&query_table[0],
NULL,
NULL
);
ExFreePool(parameter_path.Buffer);
if (!NT_SUCCESS(status)) //读取注册表信息来确定安装多少个驱动线程
{
KdPrint(("FileDisk: Query registry failed, using default values./n"));
n_devices = DEFAULT_NUMBEROFDEVICES;
}
RtlInitUnicodeString(&device_dir_name, DEVICE_DIR_NAME); //在.h头文件定义为"//Device//filedisk"
//获取驱动属性,为下面的zwCreatexxx准备
InitializeObjectAttributes(
&object_attributes,
&device_dir_name,
OBJ_PERMANENT,
NULL,
NULL
);
status = ZwCreateDirectoryObject(
&dir_handle,
DIRECTORY_ALL_ACCESS,
&object_attributes
); //SDK下CreateDirectoryObject的边种,所有zwCreateFile,zwOpenKey,zwWriteFile都是win32 API的翻版
if (!NT_SUCCESS(status))
{
return status;
}
ZwMakeTemporaryObject(dir_handle);//创建临时档
for (n = 0, n_created_devices = 0; n < n_devices; n++) //n_devices由上面的注册表读取获得
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_DISK); //挂载磁盘驱动器,载FILE_DEVICE在ntddk.h里,在DDK手册的Specifying Device Types专题
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
for (n = 0; n < n_devices; n++)
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_CD_ROM); //挂载CD驱动器
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
if (n_created_devices == 0)
{
ZwClose(dir_handle);
return status;
}
//filedisk过滤器的IRP消息->处理函数映射
DriverObject->MajorFunction[IRP_MJ_CREATE] = FileDiskCreateClose;//响应建立关闭
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FileDiskReadWrite;//响应一般读写
DriverObject->MajorFunction[IRP_MJ_WRITE] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl; //设置IRP控制函数
//设置卸载规则
DriverObject->DriverUnload = FileDiskUnload;
return STATUS_SUCCESS;
}
//创建虚拟设备的子函数,整个虚拟驱动的关键,输入参数: (PDO对象,驱动器序列数,驱动类型)
NTSTATUS
FileDiskCreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG Number,
IN DEVICE_TYPE DeviceType
)
{
WCHAR device_name_buffer[MAXIMUM_FILENAME_LENGTH];
UNICODE_STRING device_name;
NTSTATUS status;
PDEVICE_OBJECT device_object; //新建的虚拟设备PDO
PDEVICE_EXTENSION device_extension;
HANDLE thread_handle;//新建线程的操作句柄
ASSERT(DriverObject != NULL); //对象不存在,抛出debug异常;
//格式化虚拟设备名,UNICODE标准
if (DeviceType == FILE_DEVICE_CD_ROM)
{
swprintf(
device_name_buffer,
DEVICE_NAME_PREFIX L"Cd" L"%u", //L"字符串串"为字符串合并
Number
);
}
else
{
swprintf(
device_name_buffer,
DEVICE_NAME_PREFIX L"%u",
Number
);
}
RtlInitUnicodeString(&device_name, device_name_buffer);
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION), //分配磁盘空间
&device_name, //设定新驱动名字
DeviceType, //参数入口的DeviceType传递到这里了
0,
FALSE, //支持overlapped I/O多线程操作
&device_object
);
if (!NT_SUCCESS(status))
{
return status;
}
device_object->Flags |= DO_DIRECT_IO; //初始化的通常动作,这种模式需要为IRP_MJ_WRITE和IRP_MJ_READ请求创建MDL空间,那是一个系统全局缓冲区
//设备扩展结构,用来维护一些常规性操作,此结构为自定义结构
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
device_extension->media_in_device = FALSE;
if (DeviceType == FILE_DEVICE_CD_ROM)
{
device_object->Characteristics |= FILE_READ_ONLY_DEVICE; //如果是CD-ROM的话就设定为只读
device_extension->read_only = TRUE;
}
if (DeviceType == FILE_DEVICE_SMARTCARD)
{
device_object->Characteristics = FILE_REMOVABLE_MEDIA; //如果是磁盘的话就设定为移动媒体
device_extension->read_only = TRUE;
}
if (DeviceType == FILE_DEVICE_DISK)
{
device_object->Characteristics = FILE_REMOVABLE_MEDIA; //如果是磁盘的话就设定为移动媒体
device_extension->read_only = TRUE;
}
//为IRP消息而设的双向循环链表结构
InitializeListHead(&device_extension->list_head);
//自旋锁初始化,锁住双向链表,在线程处理中解锁
KeInitializeSpinLock(&device_extension->list_lock);
//设置同步事件
KeInitializeEvent(
&device_extension->request_event,
SynchronizationEvent, //同步事件操作,在每一次wait通过后自动将事件设为未受信状态,使下一次wait阻塞.NotificationEvent则不会自动设置,需要手动
FALSE //初始状态为未受信状态
);
//设置线程有效
device_extension->terminate_thread = FALSE;
//建立主线程,实际上一个盘只有一个线程操作
status = PsCreateSystemThread(
&thread_handle, //获得线程句柄
(ACCESS_MASK) 0L, //屏蔽消息
NULL,
NULL,
NULL,
FileDiskThread, //触发磁盘操作线程
device_object
);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(device_object);
return status;
}
//返回线程真实地址并保存到thread_pointer
status = ObReferenceObjectByHandle(
thread_handle,
THREAD_ALL_ACCESS,
NULL,
KernelMode, //消息类型为核心态模式
&device_extension->thread_pointer,
NULL
);
if (!NT_SUCCESS(status))
{
ZwClose(thread_handle);//释放线程建立时的操作句柄
//结束线程标志置位,结束线程
device_extension->terminate_thread = TRUE;
//触发事件结束线程
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0, //当事件受信触发下一步操作时,设置事件优先级提高的递增量
FALSE//Wait等待通过后自动设回未受信状态
);
//删除对象
IoDeleteDevice(device_object);
return status;
}
ZwClose(thread_handle);
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
//驱动卸载响应
VOID
FileDiskUnload (
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT device_object;
PAGED_CODE();
device_object = DriverObject->DeviceObject;
while (device_object)
{
device_object = FileDiskDeleteDevice(device_object);//此函数返回下一PDO对象,通过循环释放所有PDO
}
ZwClose(dir_handle);
}
PDEVICE_OBJECT
FileDiskDeleteDevice (
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION device_extension;
PDEVICE_OBJECT next_device_object;
PAGED_CODE();//保证 IRQL <= DISPATCH_LEVEL
ASSERT(DeviceObject != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//结束线程标志
device_extension->terminate_thread = TRUE;
//使事件受信,触发一次线程操作以结束线程
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
KeWaitForSingleObject(
device_extension->thread_pointer,
Executive,
KernelMode,
FALSE,
NULL
);
//通知扩展的操作释放
ObDereferenceObject(device_extension->thread_pointer);
//释放安全描述字
if (device_extension->security_client_context != NULL)
{
SeDeleteClientSecurity(device_extension->security_client_context);
ExFreePool(device_extension->security_client_context);
}
next_device_object = DeviceObject->NextDevice;
IoDeleteDevice(DeviceObject);
//返回下一个设备的指针
return next_device_object;
}
NTSTATUS
FileDiskCreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PAGED_CODE();
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
//完成响应,若IRPL>DISPATCH_LEVEL则会使调用程序处于等待状态,
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
#pragma code_seg()
NTSTATUS
FileDiskReadWrite (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PIO_STACK_LOCATION io_stack;
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
if (!device_extension->media_in_device)//虚拟盘内没介质则出错
{
Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEDIA_IN_DEVICE;
}
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (io_stack->Parameters.Read.Length == 0)//如果没数据,直接返回
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//标识IRP已经处理
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//返回成功
return STATUS_SUCCESS;
}
//通知客户端等IRP_MJ_READ/WRITE的响应
IoMarkIrpPending(Irp);
//插入到Irq处理队列链头
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
//触发线程事件
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
//返回等待处理响应
return STATUS_PENDING;
}
//IRP信息处理
NTSTATUS
FileDiskDeviceControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PIO_STACK_LOCATION io_stack;
NTSTATUS status;
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (!device_extension->media_in_device &&
io_stack->Parameters.DeviceIoControl.IoControlCode !=
IOCTL_FILE_DISK_OPEN_FILE)
{//监测到没介质,返回提示
Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEDIA_IN_DEVICE;
}
switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_FILE_DISK_OPEN_FILE:
{
SECURITY_QUALITY_OF_SERVICE security_quality_of_service;
if (device_extension->media_in_device)
{
KdPrint(("FileDisk: IOCTL_FILE_DISK_OPEN_FILE: Media already opened/n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(OPEN_FILE_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(OPEN_FILE_INFORMATION) +
((POPEN_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->FileNameLength -
sizeof(UCHAR))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
if (device_extension->security_client_context != NULL)
{ //区域保护
SeDeleteClientSecurity(device_extension->security_client_context);
}
else
{ //设置保护区域
device_extension->security_client_context =
ExAllocatePool(NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT));
}
RtlZeroMemory(&security_quality_of_service, sizeof(SECURITY_QUALITY_OF_SERVICE));
security_quality_of_service.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
security_quality_of_service.ImpersonationLevel = SecurityImpersonation;
security_quality_of_service.ContextTrackingMode = SECURITY_STATIC_TRACKING;
security_quality_of_service.EffectiveOnly = FALSE;
SeCreateClientSecurity(
PsGetCurrentThread(),
&security_quality_of_service,
FALSE,
device_extension->security_client_context
);
//设置IRP等待,通过主线程处理
IoMarkIrpPending(Irp);
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
status = STATUS_PENDING;
break;
}
case IOCTL_FILE_DISK_CLOSE_FILE:
{//通过主线程处理
IoMarkIrpPending(Irp);
ExInterlockedInsertTailList(
&device_extension->list_head,
&Irp->Tail.Overlay.ListEntry,
&device_extension->list_lock
);
KeSetEvent(
&device_extension->request_event,
(KPRIORITY) 0,
FALSE
);
status = STATUS_PENDING;
break;
}
case IOCTL_FILE_DISK_QUERY_FILE:
{
POPEN_FILE_INFORMATION open_file_information;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(OPEN_FILE_INFORMATION) + device_extension->file_name.Length - sizeof(UCHAR))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
open_file_information->FileSize.QuadPart = device_extension->file_size.QuadPart;
open_file_information->ReadOnly = device_extension->read_only;
open_file_information->FileNameLength = device_extension->file_name.Length;
RtlCopyMemory(
open_file_information->FileName,
device_extension->file_name.Buffer,
device_extension->file_name.Length
);
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(OPEN_FILE_INFORMATION) +
open_file_information->FileNameLength - sizeof(UCHAR);
break;
}
case IOCTL_DISK_CHECK_VERIFY:
case IOCTL_CDROM_CHECK_VERIFY:
case IOCTL_STORAGE_CHECK_VERIFY:
case IOCTL_STORAGE_CHECK_VERIFY2:
{ //默认处理
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
{//物理参数处理
PDISK_GEOMETRY disk_geometry;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_GEOMETRY))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
disk_geometry->Cylinders.QuadPart = length / SECTOR_SIZE / 32 / 2;
disk_geometry->MediaType = FixedMedia;
disk_geometry->TracksPerCylinder = 2;
disk_geometry->SectorsPerTrack = 32;
disk_geometry->BytesPerSector = SECTOR_SIZE;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
break;
}
case IOCTL_DISK_GET_LENGTH_INFO:
{
PGET_LENGTH_INFORMATION get_length_information;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(GET_LENGTH_INFORMATION))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
get_length_information = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
get_length_information->Length.QuadPart = device_extension->file_size.QuadPart;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
break;
}
case IOCTL_DISK_GET_PARTITION_INFO:
{//获取分区信息
PPARTITION_INFORMATION partition_information;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
partition_information->StartingOffset.QuadPart = 0;
partition_information->PartitionLength.QuadPart = length;
partition_information->HiddenSectors = 1;
partition_information->PartitionNumber = 0;
partition_information->PartitionType = 0;
partition_information->BootIndicator = FALSE;
partition_information->RecognizedPartition = FALSE;
partition_information->RewritePartition = FALSE;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
break;
}
//分区表额外信息
case IOCTL_DISK_GET_PARTITION_INFO_EX:
{
PPARTITION_INFORMATION_EX partition_information_ex;
ULONGLONG length;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION_EX))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information_ex = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
length = device_extension->file_size.QuadPart;
partition_information_ex->PartitionStyle = PARTITION_STYLE_MBR;
partition_information_ex->StartingOffset.QuadPart = 0;
partition_information_ex->PartitionLength.QuadPart = length;
partition_information_ex->PartitionNumber = 0;
partition_information_ex->RewritePartition = FALSE;
partition_information_ex->Mbr.PartitionType = 0;
partition_information_ex->Mbr.BootIndicator = FALSE;
partition_information_ex->Mbr.RecognizedPartition = FALSE;
partition_information_ex->Mbr.HiddenSectors = 1;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
break;
}
//设备是否可写
case IOCTL_DISK_IS_WRITABLE:
{
if (!device_extension->read_only)
{
status = STATUS_SUCCESS;
}
else
{
status = STATUS_MEDIA_WRITE_PROTECTED;
}
Irp->IoStatus.Information = 0;
break;
}
//设施是否可移动
case IOCTL_DISK_MEDIA_REMOVAL:
case IOCTL_STORAGE_MEDIA_REMOVAL:
{
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_CDROM_READ_TOC:
{
PCDROM_TOC cdrom_toc;
if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(CDROM_TOC))
{
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
cdrom_toc = (PCDROM_TOC) Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(cdrom_toc, sizeof(CDROM_TOC));
cdrom_toc->FirstTrack = 1;
cdrom_toc->LastTrack = 1;
cdrom_toc->TrackData[0].Control = TOC_DATA_TRACK;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(CDROM_TOC);
break;
}
case IOCTL_DISK_SET_PARTITION_INFO:
{
if (device_extension->read_only)
{
status = STATUS_MEDIA_WRITE_PROTECTED;
Irp->IoStatus.Information = 0;
break;
}
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SET_PARTITION_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
case IOCTL_DISK_VERIFY:
{//磁盘检验
PVERIFY_INFORMATION verify_information;
if (io_stack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(VERIFY_INFORMATION))
{
status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = verify_information->Length;
break;
}
default:
{//默认处理
KdPrint((
"FileDisk: Unknown IoControlCode %#x/n",
io_stack->Parameters.DeviceIoControl.IoControlCode
));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
}
}
if (status != STATUS_PENDING)
{
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
//操作处理线程,输入参数(空指针化的PDO),此线程由FileDiskDeviceDevice调用,在驱动被调用时启动,完成初始化操作.
VOID
FileDiskThread (
IN PVOID Context
)
{
PDEVICE_OBJECT device_object;
PDEVICE_EXTENSION device_extension;
PLIST_ENTRY request; //双向链表的IRP栈
PIRP irp;
PIO_STACK_LOCATION io_stack;
PUCHAR system_buffer;
PUCHAR buffer;
ASSERT(Context != NULL);
device_object = (PDEVICE_OBJECT) Context;
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
//设置优先级
KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
for (;;)//以下为线程的无限循环,当device_extension->terminate_thread设为true时才结束.
{
//等待request_event事件置信,for每循环一次,在这里被阻塞,等待
KeWaitForSingleObject(
&device_extension->request_event,
Executive,
KernelMode,
FALSE,
NULL
);
//如果结束线程标志置位,结束线程
if (device_extension->terminate_thread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
}
//遍历IRP表
while (request = ExInterlockedRemoveHeadList(
&device_extension->list_head,
&device_extension->list_lock
)) //list不为空,则指向下一链表数据
{
irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry); //获取irp基地址,tail是IRP结构里面的一个Union结构,Tail.Overlay.ListEntry说明IRP入栈待处理
IRP的栈返回形式
io_stack = IoGetCurrentIrpStackLocation(irp);
switch (io_stack->MajorFunction)
{
case IRP_MJ_READ://读数据到内存
system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);//分配MDL虚拟地址空间
if (system_buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;//分配失败返回资源不足警告
irp->IoStatus.Information = 0;
break;
}
buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length); //分配空间
if (buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
ZwReadFile(
device_extension->file_handle, //读取指定的映像文件
NULL,
NULL,
NULL,
&irp->IoStatus,
buffer, //文件缓冲
io_stack->Parameters.Read.Length,
&io_stack->Parameters.Read.ByteOffset,
NULL
);
RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length); //将文件缓冲读入到MDL缓冲
ExFreePool(buffer);//释放文件缓冲
break;
case IRP_MJ_WRITE://内存数据写到设备
if ((io_stack->Parameters.Write.ByteOffset.QuadPart +
io_stack->Parameters.Write.Length) >
device_extension->file_size.QuadPart)//判错处理
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
irp->IoStatus.Information = 0;
}
ZwWriteFile(
device_extension->file_handle,
NULL,
NULL,
NULL,
&irp->IoStatus,
MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), //从MDL缓冲写入文件
io_stack->Parameters.Write.Length,
&io_stack->Parameters.Write.ByteOffset,
NULL
); //写文件
break;
//下面的是自定义IRP响应
case IRP_MJ_DEVICE_CONTROL:
switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_FILE_DISK_OPEN_FILE:
//nt未公开函数,应该是权限设置
SeImpersonateClient(device_extension->security_client_context, NULL);
irp->IoStatus.Status = FileDiskOpenFile(device_object, irp);
PsRevertToSelf();//nt未公开函数
break;
case IOCTL_FILE_DISK_CLOSE_FILE:
irp->IoStatus.Status = FileDiskCloseFile(device_object, irp);
break;
default:
irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
}
break;
default:
irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
}
IoCompleteRequest(
irp,
(CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?
IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
}
}
}
#pragma code_seg("PAGE")
//打开映像文件相关操作
NTSTATUS
FileDiskOpenFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
POPEN_FILE_INFORMATION open_file_information;
UNICODE_STRING ufile_name;
NTSTATUS status;
OBJECT_ATTRIBUTES object_attributes;
FILE_END_OF_FILE_INFORMATION file_eof;
FILE_BASIC_INFORMATION file_basic;
FILE_STANDARD_INFORMATION file_standard;
FILE_ALIGNMENT_INFORMATION file_alignment;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//从Irq用户提交的buffer中获取文件信息
open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
{
device_extension->read_only = open_file_information->ReadOnly;
}
//获取文件名
device_extension->file_name.Length = open_file_information->FileNameLength;
device_extension->file_name.MaximumLength = open_file_information->FileNameLength;
device_extension->file_name.Buffer = ExAllocatePool(NonPagedPool, open_file_information->FileNameLength);
RtlCopyMemory(
device_extension->file_name.Buffer,
open_file_information->FileName,
open_file_information->FileNameLength
);
status = RtlAnsiStringToUnicodeString(
&ufile_name, //转换成UNICODE路径
&device_extension->file_name,
TRUE
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
return status;
}
InitializeObjectAttributes(
&object_attributes,
&ufile_name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = ZwCreateFile( //打开映像文件
&device_extension->file_handle,
device_extension->read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&Irp->IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
device_extension->read_only ? FILE_SHARE_READ : 0,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NO_SUCH_FILE)
{
if (device_extension->read_only || open_file_information->FileSize.QuadPart == 0)
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
Irp->IoStatus.Status = STATUS_NO_SUCH_FILE;
Irp->IoStatus.Information = 0;
return STATUS_NO_SUCH_FILE;
}
else
{
status = ZwCreateFile(
&device_extension->file_handle,
GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&Irp->IoStatus,
&open_file_information->FileSize,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,//如果文件存在则打开,不存在建立
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
return status;
}
if (Irp->IoStatus.Information == FILE_CREATED)
{
file_eof.EndOfFile.QuadPart = open_file_information->FileSize.QuadPart;
status = ZwSetInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_eof,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation
);
if (!NT_SUCCESS(status))
{//释放临时量
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
ZwClose(device_extension->file_handle);
return status;
}
}
}
}
else if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
RtlFreeUnicodeString(&ufile_name);
return status;
}
RtlFreeUnicodeString(&ufile_name);
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_basic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_standard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
device_extension->file_size.QuadPart = file_standard.EndOfFile.QuadPart;
status = ZwQueryInformationFile(
device_extension->file_handle,
&Irp->IoStatus,
&file_alignment,
sizeof(FILE_ALIGNMENT_INFORMATION),
FileAlignmentInformation
);
if (!NT_SUCCESS(status))
{
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
return status;
}
DeviceObject->AlignmentRequirement = file_alignment.AlignmentRequirement;
if (device_extension->read_only)
{
DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
}
else
{
DeviceObject->Characteristics &= ~FILE_READ_ONLY_DEVICE;
}
device_extension->media_in_device = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
//映像文件关闭并释放资源函数
NTSTATUS
FileDiskCloseFile (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION device_extension;
PAGED_CODE();
ASSERT(DeviceObject != NULL);
ASSERT(Irp != NULL);
device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
ExFreePool(device_extension->file_name.Buffer);
ZwClose(device_extension->file_handle);
device_extension->media_in_device = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}