我研究filedisk的一些注解

我研究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;
}

 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值