阅读:3696回复:7
我研究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; } |
|
最新喜欢:![]() |
沙发#
发布于:2007-05-14 13:54
收藏,再学习。辛苦楼主了。
|
|
|
板凳#
发布于:2007-05-15 11:11
学习...
|
|
地板#
发布于:2007-05-15 11:37
感谢:) 大家多发表自己的学习心得,笔记
|
|
|
地下室#
发布于:2007-05-16 14:30
用户被禁言,该主题自动屏蔽! |
|
5楼#
发布于:2007-05-16 20:08
用户被禁言,该主题自动屏蔽! |
|
6楼#
发布于:2007-06-20 14:44
![]() |
|
7楼#
发布于:2007-07-26 20:05
大哥,能不能把主要的思路整理出来,这么多东西,这么个写法,还不如直接看源代码呢
比如:基本原理,驱动在什么层次,关键的操作,…… |
|
|