zoukankan      html  css  js  c++  java
  • 漫谈IRP

    I/O Request Packet(IRP)

     

    IRP概述: 

     

    IRP是由I/O管理器发出的,I/O管理器是用户态与内核态之间的桥梁,当用户态进程发出I/O请求时,I/O管理器就捕获这些请求,将其转换为IRP请求,发送给驱动程序。

    I/O管理器无疑是非常重要的,具有核心地位。它负责所有I/O请求的调度和管理工作,根据请求的不同内容,选择相应的驱动程序对象,设备对象,并生成、发送、释放各种不同的IRP。

    整个I/O处理流程是在它的指挥下完成的。

    一个IRP是从非分页内存中分配的可变大小的结构,它包括两部分:IRP首部和I/O堆栈。

    IRP首部中包含了指向IRP输入输出缓冲区指针、当前拥有IRP的驱动指针等。

    紧接着首部的IO_STACK_LOCATION结构的数组。它的大小由设备栈中的设备数确定。IO_STACK_LOCATION结构中保存了一个I/O请求的参数及代码、请求当前对应的设备指针、完成函数指针(IoCompletion)等。

     

    IRP结构介绍: 

     

    我们先看看WRK中对IRP的定义

     

      1 typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP {
      2     CSHORT Type;
      3     USHORT Size;
      4 
      5     //
      6     // Define the common fields used to control the IRP.
      7     //
      8 
      9     //
     10     // Define a pointer to the Memory Descriptor List (MDL) for this I/O
     11     // request.  This field is only used if the I/O is "direct I/O".
     12     //
     13 
     14     PMDL MdlAddress;
     15 
     16     //
     17     // Flags word - used to remember various flags.
     18     //
     19 
     20     ULONG Flags;
     21 
     22     //
     23     // The following union is used for one of three purposes:
     24     //
     25     //    1. This IRP is an associated IRP.  The field is a pointer to a master
     26     //       IRP.
     27     //
     28     //    2. This is the master IRP.  The field is the count of the number of
     29     //       IRPs which must complete (associated IRPs) before the master can
     30     //       complete.
     31     //
     32     //    3. This operation is being buffered and the field is the address of
     33     //       the system space buffer.
     34     //
     35 
     36     union {
     37         struct _IRP *MasterIrp;
     38         __volatile LONG IrpCount;
     39         PVOID SystemBuffer;
     40     } AssociatedIrp;
     41 
     42     //
     43     // Thread list entry - allows queueing the IRP to the thread pending I/O
     44     // request packet list.
     45     //
     46 
     47     LIST_ENTRY ThreadListEntry;
     48 
     49     //
     50     // I/O status - final status of operation.
     51     //
     52 
     53     IO_STATUS_BLOCK IoStatus;
     54 
     55     //
     56     // Requestor mode - mode of the original requestor of this operation.
     57     //
     58 
     59     KPROCESSOR_MODE RequestorMode;
     60 
     61     //
     62     // Pending returned - TRUE if pending was initially returned as the
     63     // status for this packet.
     64     //
     65 
     66     BOOLEAN PendingReturned;
     67 
     68     //
     69     // Stack state information.
     70     //
     71 
     72     CHAR StackCount;
     73     CHAR CurrentLocation;
     74 
     75     //
     76     // Cancel - packet has been canceled.
     77     //
     78 
     79     BOOLEAN Cancel;
     80 
     81     //
     82     // Cancel Irql - Irql at which the cancel spinlock was acquired.
     83     //
     84 
     85     KIRQL CancelIrql;
     86 
     87     //
     88     // ApcEnvironment - Used to save the APC environment at the time that the
     89     // packet was initialized.
     90     //
     91 
     92     CCHAR ApcEnvironment;
     93 
     94     //
     95     // Allocation control flags.
     96     //
     97 
     98     UCHAR AllocationFlags;
     99 
    100     //
    101     // User parameters.
    102     //
    103 
    104     PIO_STATUS_BLOCK UserIosb;
    105     PKEVENT UserEvent;
    106     union {
    107         struct {
    108             union {
    109                 PIO_APC_ROUTINE UserApcRoutine;
    110                 PVOID IssuingProcess;
    111             };
    112             PVOID UserApcContext;
    113         } AsynchronousParameters;
    114         LARGE_INTEGER AllocationSize;
    115     } Overlay;
    116 
    117     //
    118     // CancelRoutine - Used to contain the address of a cancel routine supplied
    119     // by a device driver when the IRP is in a cancelable state.
    120     //
    121 
    122     __volatile PDRIVER_CANCEL CancelRoutine;
    123 
    124     //
    125     // Note that the UserBuffer parameter is outside of the stack so that I/O
    126     // completion can copy data back into the user's address space without
    127     // having to know exactly which service was being invoked.  The length
    128     // of the copy is stored in the second half of the I/O status block. If
    129     // the UserBuffer field is NULL, then no copy is performed.
    130     //
    131 
    132     PVOID UserBuffer;
    133 
    134     //
    135     // Kernel structures
    136     //
    137     // The following section contains kernel structures which the IRP needs
    138     // in order to place various work information in kernel controller system
    139     // queues.  Because the size and alignment cannot be controlled, they are
    140     // placed here at the end so they just hang off and do not affect the
    141     // alignment of other fields in the IRP.
    142     //
    143 
    144     union {
    145 
    146         struct {
    147 
    148             union {
    149 
    150                 //
    151                 // DeviceQueueEntry - The device queue entry field is used to
    152                 // queue the IRP to the device driver device queue.
    153                 //
    154 
    155                 KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
    156 
    157                 struct {
    158 
    159                     //
    160                     // The following are available to the driver to use in
    161                     // whatever manner is desired, while the driver owns the
    162                     // packet.
    163                     //
    164 
    165                     PVOID DriverContext[4];
    166 
    167                 } ;
    168 
    169             } ;
    170 
    171             //
    172             // Thread - pointer to caller's Thread Control Block.
    173             //
    174 
    175             PETHREAD Thread;
    176 
    177             //
    178             // Auxiliary buffer - pointer to any auxiliary buffer that is
    179             // required to pass information to a driver that is not contained
    180             // in a normal buffer.
    181             //
    182 
    183             PCHAR AuxiliaryBuffer;
    184 
    185             //
    186             // The following unnamed structure must be exactly identical
    187             // to the unnamed structure used in the minipacket header used
    188             // for completion queue entries.
    189             //
    190 
    191             struct {
    192 
    193                 //
    194                 // List entry - used to queue the packet to completion queue, among
    195                 // others.
    196                 //
    197 
    198                 LIST_ENTRY ListEntry;
    199 
    200                 union {
    201 
    202                     //
    203                     // Current stack location - contains a pointer to the current
    204                     // IO_STACK_LOCATION structure in the IRP stack.  This field
    205                     // should never be directly accessed by drivers.  They should
    206                     // use the standard functions.
    207                     //
    208 
    209                     struct _IO_STACK_LOCATION *CurrentStackLocation;
    210 
    211                     //
    212                     // Minipacket type.
    213                     //
    214 
    215                     ULONG PacketType;
    216                 };
    217             };
    218 
    219             //
    220             // Original file object - pointer to the original file object
    221             // that was used to open the file.  This field is owned by the
    222             // I/O system and should not be used by any other drivers.
    223             //
    224 
    225             PFILE_OBJECT OriginalFileObject;
    226 
    227         } Overlay;
    228 
    229         //
    230         // APC - This APC control block is used for the special kernel APC as
    231         // well as for the caller's APC, if one was specified in the original
    232         // argument list.  If so, then the APC is reused for the normal APC for
    233         // whatever mode the caller was in and the "special" routine that is
    234         // invoked before the APC gets control simply deallocates the IRP.
    235         //
    236 
    237         KAPC Apc;
    238 
    239         //
    240         // CompletionKey - This is the key that is used to distinguish
    241         // individual I/O operations initiated on a single file handle.
    242         //
    243 
    244         PVOID CompletionKey;
    245 
    246     } Tail;
    247 
    248 } IRP;
    View Code

    结构图如下,其中灰色部分为不可见区域,这里主要讲解一下可见区域。

    1.1 PMDL  MdlAddress : 设备执行直接I/O时,指向用户空间的内存描述表

    1.2 ULONG Flags: 包含一些对驱动程序只读的标志。但这些标志与WDM驱动程序无关

    1.3 AssociatedIrp.SystemBuffer : SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,这也是创建IRP过程的一部分。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。

    1.4 IoStatus : 是一个结构体IO_STATUS_BLOCK, 这个结构体仅包含两个域,驱动程序在最终完成请求时设置这个结构。
           IoStatus.Status : 将收到一个NTSTATUS代码。
           IoStatus.Information 的类型为ULONG_PTR,它将收到一个信息值,该信息值的确切含义要取决于具体的IRP类型和请求完成的状态。Information域的一个公认用法是用于保存数据传输操作。某些PnP请求把这个域作为指向另外一个结构的指针,这个结构通常包含查询请求的结果。

    1.5 RequestorMode将等于一个枚举常量UserModeKernelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。

    1.6 PendingReturned(BOOLEAN)如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。完成例程通过参考该域来避免自己与派遣例程间的潜在竞争。

    1.7 Cancel(BOOLEAN)如果为TRUE,则表明IoCancelIrp已被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIrp函数。取消IRP是一个相对复杂的主题,我将在本章的最后详细描述它。

    1.8 CancelIrql(KIRQL)是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的。当你在取消例程中释放自旋锁时应参考这个域。

    1.9 CancelRoutine(PDRIVER_CANCEL)是驱动程序取消例程的地址。你应该使用IoSetCancelRoutine函数设置这个域而不是直接修改该域。

    2.0 UserBuffer(PVOID) 对于METHOD_NEITHER方式的IRP_MJ_DEVICE_CONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请求缓冲区的用户模式虚拟地址,但指定了DO_BUFFERED_IO或DO_DIRECT_IO标志的驱动程序,其读写例程通常不需要访问这个域。当处理一个METHOD_NEITHER控制操作时,驱动程序能用这个地址创建自己的MDL。

    PIO_STACK_LOCATION结构介绍: 

    我们再来看看WRK中对PIO_STACK_LOCATION结构的定义

    typedef struct _IO_STACK_LOCATION {
        UCHAR MajorFunction;
        UCHAR MinorFunction;
        UCHAR Flags;
        UCHAR Control;
    
        //
        // The following user parameters are based on the service that is being
        // invoked.  Drivers and file systems can determine which set to use based
        // on the above major and minor function codes.
        //
    
        union {
    
            //
            // System service parameters for:  NtCreateFile
            //
    
            struct {
                PIO_SECURITY_CONTEXT SecurityContext;
                ULONG Options;
                USHORT POINTER_ALIGNMENT FileAttributes;
                USHORT ShareAccess;
                ULONG POINTER_ALIGNMENT EaLength;
            } Create;
    
    
            //
            // System service parameters for:  NtReadFile
            //
    
            struct {
                ULONG Length;
                ULONG POINTER_ALIGNMENT Key;
                LARGE_INTEGER ByteOffset;
            } Read;
    
            //
            // System service parameters for:  NtWriteFile
            //
    
            struct {
                ULONG Length;
                ULONG POINTER_ALIGNMENT Key;
                LARGE_INTEGER ByteOffset;
            } Write;
    
            //
            // System service parameters for:  NtQueryDirectoryFile
            //
    
            struct {
                ULONG Length;
                PUNICODE_STRING FileName;
                FILE_INFORMATION_CLASS FileInformationClass;
                ULONG POINTER_ALIGNMENT FileIndex;
            } QueryDirectory;
    
            //
            // System service parameters for:  NtNotifyChangeDirectoryFile
            //
    
            struct {
                ULONG Length;
                ULONG POINTER_ALIGNMENT CompletionFilter;
            } NotifyDirectory;
    
            //
            // System service parameters for:  NtQueryInformationFile
            //
    
            struct {
                ULONG Length;
                FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
            } QueryFile;
    
            //
            // System service parameters for:  NtSetInformationFile
            //
    
            struct {
                ULONG Length;
                FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
                PFILE_OBJECT FileObject;
                union {
                    struct {
                        BOOLEAN ReplaceIfExists;
                        BOOLEAN AdvanceOnly;
                    };
                    ULONG ClusterCount;
                    HANDLE DeleteHandle;
                };
            } SetFile;
    
    
    
            //
            // System service parameters for:  NtQueryEaFile
            //
    
            struct {
                ULONG Length;
                PVOID EaList;
                ULONG EaListLength;
                ULONG POINTER_ALIGNMENT EaIndex;
            } QueryEa;
    
            //
            // System service parameters for:  NtSetEaFile
            //
    
            struct {
                ULONG Length;
            } SetEa;
    
    
    
            //
            // System service parameters for:  NtQueryVolumeInformationFile
            //
    
            struct {
                ULONG Length;
                FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
            } QueryVolume;
    
    
    
            //
            // System service parameters for:  NtSetVolumeInformationFile
            //
    
            struct {
                ULONG Length;
                FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
            } SetVolume;
    
            //
            // System service parameters for:  NtFsControlFile
            //
            // Note that the user's output buffer is stored in the UserBuffer field
            // and the user's input buffer is stored in the SystemBuffer field.
            //
    
            struct {
                ULONG OutputBufferLength;
                ULONG POINTER_ALIGNMENT InputBufferLength;
                ULONG POINTER_ALIGNMENT FsControlCode;
                PVOID Type3InputBuffer;
            } FileSystemControl;
            //
            // System service parameters for:  NtLockFile/NtUnlockFile
            //
    
            struct {
                PLARGE_INTEGER Length;
                ULONG POINTER_ALIGNMENT Key;
                LARGE_INTEGER ByteOffset;
            } LockControl;
    
            //
            // System service parameters for:  NtFlushBuffersFile
            //
            // No extra user-supplied parameters.
            //
    
    
    
            //
            // System service parameters for:  NtCancelIoFile
            //
            // No extra user-supplied parameters.
            //
    
    
    
            //
            // System service parameters for:  NtDeviceIoControlFile
            //
            // Note that the user's output buffer is stored in the UserBuffer field
            // and the user's input buffer is stored in the SystemBuffer field.
            //
    
            struct {
                ULONG OutputBufferLength;
                ULONG POINTER_ALIGNMENT InputBufferLength;
                ULONG POINTER_ALIGNMENT IoControlCode;
                PVOID Type3InputBuffer;
            } DeviceIoControl;
    
            //
            // System service parameters for:  NtQuerySecurityObject
            //
    
            struct {
                SECURITY_INFORMATION SecurityInformation;
                ULONG POINTER_ALIGNMENT Length;
            } QuerySecurity;
    
            //
            // System service parameters for:  NtSetSecurityObject
            //
    
            struct {
                SECURITY_INFORMATION SecurityInformation;
                PSECURITY_DESCRIPTOR SecurityDescriptor;
            } SetSecurity;
    
            //
            // Non-system service parameters.
            //
            // Parameters for MountVolume
            //
    
            struct {
                PVPB Vpb;
                PDEVICE_OBJECT DeviceObject;
            } MountVolume;
    
            //
            // Parameters for VerifyVolume
            //
    
            struct {
                PVPB Vpb;
                PDEVICE_OBJECT DeviceObject;
            } VerifyVolume;
    
            //
            // Parameters for Scsi with internal device contorl.
            //
    
            struct {
                struct _SCSI_REQUEST_BLOCK *Srb;
            } Scsi;
    
    
    
            //
            // System service parameters for:  NtQueryQuotaInformationFile
            //
    
            struct {
                ULONG Length;
                PSID StartSid;
                PFILE_GET_QUOTA_INFORMATION SidList;
                ULONG SidListLength;
            } QueryQuota;
    
            //
            // System service parameters for:  NtSetQuotaInformationFile
            //
    
            struct {
                ULONG Length;
            } SetQuota;
    
    
    
            //
            // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS
            //
    
            struct {
                DEVICE_RELATION_TYPE Type;
            } QueryDeviceRelations;
    
            //
            // Parameters for IRP_MN_QUERY_INTERFACE
            //
    
            struct {
                CONST GUID *InterfaceType;
                USHORT Size;
                USHORT Version;
                PINTERFACE Interface;
                PVOID InterfaceSpecificData;
            } QueryInterface;
    
            //
            // Parameters for IRP_MN_QUERY_CAPABILITIES
            //
    
            struct {
                PDEVICE_CAPABILITIES Capabilities;
            } DeviceCapabilities;
    
            //
            // Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS
            //
    
            struct {
                PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList;
            } FilterResourceRequirements;
    
            //
            // Parameters for IRP_MN_READ_CONFIG and IRP_MN_WRITE_CONFIG
            //
    
            struct {
                ULONG WhichSpace;
                PVOID Buffer;
                ULONG Offset;
                ULONG POINTER_ALIGNMENT Length;
            } ReadWriteConfig;
    
            //
            // Parameters for IRP_MN_SET_LOCK
            //
    
            struct {
                BOOLEAN Lock;
            } SetLock;
    
            //
            // Parameters for IRP_MN_QUERY_ID
            //
    
            struct {
                BUS_QUERY_ID_TYPE IdType;
            } QueryId;
    
            //
            // Parameters for IRP_MN_QUERY_DEVICE_TEXT
            //
    
            struct {
                DEVICE_TEXT_TYPE DeviceTextType;
                LCID POINTER_ALIGNMENT LocaleId;
            } QueryDeviceText;
    
            //
            // Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION
            //
    
            struct {
                BOOLEAN InPath;
                BOOLEAN Reserved[3];
                DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
            } UsageNotification;
    
            //
            // Parameters for IRP_MN_WAIT_WAKE
            //
    
            struct {
                SYSTEM_POWER_STATE PowerState;
            } WaitWake;
    
            //
            // Parameter for IRP_MN_POWER_SEQUENCE
            //
    
            struct {
                PPOWER_SEQUENCE PowerSequence;
            } PowerSequence;
    
            //
            // Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER
            //
    
    #if (NTDDI_VERSION >= NTDDI_VISTA)
            struct {
                union {
                    ULONG SystemContext;
                    SYSTEM_POWER_STATE_CONTEXT SystemPowerStateContext;
                };
                POWER_STATE_TYPE POINTER_ALIGNMENT Type;
                POWER_STATE POINTER_ALIGNMENT State;
                POWER_ACTION POINTER_ALIGNMENT ShutdownType;
            } Power;
    #else
            struct {
                ULONG SystemContext;
                POWER_STATE_TYPE POINTER_ALIGNMENT Type;
                POWER_STATE POINTER_ALIGNMENT State;
                POWER_ACTION POINTER_ALIGNMENT ShutdownType;
            } Power;
    #endif // (NTDDI_VERSION >= NTDDI_VISTA)
    
            //
            // Parameters for StartDevice
            //
    
            struct {
                PCM_RESOURCE_LIST AllocatedResources;
                PCM_RESOURCE_LIST AllocatedResourcesTranslated;
            } StartDevice;
    
            //
            // Parameters for Cleanup
            //
            // No extra parameters supplied
            //
    
            //
            // WMI Irps
            //
    
            struct {
                ULONG_PTR ProviderId;
                PVOID DataPath;
                ULONG BufferSize;
                PVOID Buffer;
            } WMI;
    
            //
            // Others - driver-specific
            //
    
            struct {
                PVOID Argument1;
                PVOID Argument2;
                PVOID Argument3;
                PVOID Argument4;
            } Others;
    
        } Parameters;
    
        //
        // Save a pointer to this device driver's device object for this request
        // so it can be passed to the completion routine if needed.
        //
    
        PDEVICE_OBJECT DeviceObject;
    
        //
        // The following location contains a pointer to the file object for this
        // request.
        //
    
        PFILE_OBJECT FileObject;
    
        //
        // The following routine is invoked depending on the flags in the above
        // flags field.
        //
    
        PIO_COMPLETION_ROUTINE CompletionRoutine;
    
        //
        // The following is used to store the address of the context parameter
        // that should be passed to the CompletionRoutine.
        //
    
        PVOID Context;
    
    } IO_STACK_LOCATION, *PIO_STACK_LOCATION;
    View Code

    结构图如下

    MajorFunction(UCHAR)是该IRP的主功能码

    MinorFunction(UCHAR)是该IRP的副功能码

    Parameters(union)是几个子结构的联合,每个请求类型都有自己专用的参数,而每个子结构就是一种参数。这些子结构包括Create(IRP_MJ_CREATE请求)、Read(IRP_MJ_READ请求)、StartDevice(IRP_MJ_PNP的IRP_MN_START_DEVICE子类型),等等。

    DeviceObject(PDEVICE_OBJECT)是与该堆栈单元对应的设备对象的地址。该域由IoCallDriver函数负责填写。

    FileObject(PFILE_OBJECT)是内核文件对象的地址,IRP的目标就是这个文件对象。驱动程序通常在处理清除请求(IRP_MJ_CLEANUP)时使用FileObject指针,以区分队列中与该文件对象无关的IRP。

    CompletionRoutine(PIO_COMPLETION_ROUTINE)是一个I/O完成例程的地址,该地址是由与这个堆栈单元对应的驱动程序的更上一层驱动程序设置的。你绝对不要直接设置这个域,应该调用IoSetCompletionRoutine函数,该函数知道如何参考下一层驱动程序的堆栈单元。设备堆栈的最低一级驱动程序并不需要完成例程,因为它们必须直接完成请求。然而,请求的发起者有时确实需要一个完成例程,但通常没有自己的堆栈单元。这就是为什么每一级驱动程序都使用下一级驱动程序的堆栈单元保存自己完成例程指针的原因。

    IRP、PIO_STACK_LOCATIONDEVICE:

    1)I/O堆栈位置的主要目的是,保存一个I/O请求的函数代码和参数。
    2)I/O堆栈数量实际上就是参与I/O请求的I/O层的数量。
    3)在一个IRP中,上层驱动负责为下层驱动设置堆栈位置指针。
      i)驱动程序可以为每个IRP调用IoGetCurrentStackLocation来获得指向其自身堆栈位置的指针,
      ii)上层驱动程序必须调用IoGetNextIrpStackLocation来获得指向下层驱动程序堆栈位置的指针。
    因此,上层驱动可以在传送IRP给下层驱动之前设置堆栈位置的内容。
    4)上层驱动调用IoCallDriver,将DeviceObject成员设置成下层驱动目标设备对象。当上层驱动完成IRP时,IoCompletion 函数被调用,I/O管理器传送给IoCompletion函数一个指向上层驱动的设备对象的指针。

    示例:

    下面我们通过构造IPR去删除一个文件来加深对IPR的认识

      1 #include "DeleteFile.h"
      2 
      3 NTSTATUS
      4 DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath)
      5 {
      6 
      7     HANDLE hFile = GetFileHandle(L"\\??\\D:\\1.exe");
      8     DriverObject->DriverUnload = UnloadDriver;
      9 
     10     if (hFile!=NULL)
     11     {
     12         
     13         DbgPrint("Get File Success\r\n");
     14         DestroyFile(hFile);
     15         
     16         ZwClose(hFile);
     17     }
     18 
     19     return STATUS_SUCCESS;
     20 }
     21 
     22 
     23 VOID
     24 UnloadDriver(PDRIVER_OBJECT DriverObject)
     25 {
     26 
     27 }
     28 
     29 
     30 HANDLE
     31 GetFileHandle(PCWSTR  FileName)
     32 {
     33     
     34     NTSTATUS        Status;
     35     UNICODE_STRING  uniFileName;
     36     OBJECT_ATTRIBUTES oa;
     37     HANDLE            hFile;
     38     IO_STATUS_BLOCK Iosb;
     39     
     40     RtlInitUnicodeString(&uniFileName,FileName);
     41     
     42     InitializeObjectAttributes(&oa,&uniFileName,
     43         OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,NULL,NULL);
     44     
     45     //通过文件名得文件句柄
     46     Status = IoCreateFile(&hFile,FILE_READ_ATTRIBUTES,
     47         &oa,&Iosb,0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_DELETE,FILE_OPEN,0,NULL,0,0,NULL,
     48         IO_NO_PARAMETER_CHECKING);
     49     
     50     
     51     if (!NT_SUCCESS(Status))
     52     {
     53         return NULL;
     54     }
     55     
     56     return hFile;
     57     
     58 }
     59 
     60 
     61 VOID 
     62 DestroyFile(HANDLE hFile)
     63 {
     64 
     65     IO_STATUS_BLOCK            Iosb;
     66     PIO_STACK_LOCATION        IrpSp;
     67     NTSTATUS                Status;
     68     PFILE_OBJECT            FileObject;
     69     PIRP                    Irp;
     70     PDEVICE_OBJECT            DeviceObject;
     71     KEVENT                    hEvent;
     72     FILE_DISPOSITION_INFORMATION        FileInfor;//微软官方结构体
     73 
     74 
     75     static PVOID ImageSectionObject = NULL;
     76     static PVOID DataSectionObject  = NULL;
     77     static PVOID SharedCacheMap     = NULL;
     78 
     79     //通过文件句柄得文件对象
     80     Status = ObReferenceObjectByHandle(hFile,DELETE,*IoFileObjectType,KernelMode,
     81         &FileObject,NULL);
     82 
     83 
     84     DeviceObject = IoGetRelatedDeviceObject(FileObject);   //文件系统栈最上层的设备对象    //也可以获得卷设备直接发送
     85 
     86 
     87 
     88     //去除文件的只读属性
     89     if (SKillStripFileAttributes(hFile)==FALSE)
     90     {
     91         return;
     92     }
     93     //构建一个IRP
     94 
     95     Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
     96     if (Irp==NULL)
     97     {
     98         ObDereferenceObject(FileObject);
     99     
    100         return;
    101     }
    102 
    103 
    104     KeInitializeEvent(&hEvent,SynchronizationEvent,FALSE);
    105 
    106 
    107     FileInfor.DeleteFile = TRUE;
    108 
    109 
    110     Irp->AssociatedIrp.SystemBuffer = &FileInfor;
    111     Irp->UserEvent = &hEvent;
    112     Irp->UserIosb = &Iosb; 
    113     Irp->Tail.Overlay.OriginalFileObject = FileObject;
    114     Irp->Tail.Overlay.Thread = KeGetCurrentThread();
    115     Irp->RequestorMode = KernelMode;
    116 
    117 
    118     IrpSp = IoGetNextIrpStackLocation(Irp);
    119 
    120     IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
    121 
    122     IrpSp->DeviceObject = DeviceObject;// Irp栈中保存的设备对象是文件系统设备对象
    123     IrpSp->FileObject = FileObject;   //
    124 
    125     IrpSp->Parameters.SetFile.FileObject = FileObject;
    126     IrpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
    127     IrpSp->Parameters.SetFile.FileObject = FileObject;
    128 
    129     IrpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
    130 
    131 
    132     //将文件的物理页面的属性先保存起来
    133     //文件对象指向的物理页(IRP会对他进行检测,如果不为空不删除文件)
    134     if (MmIsAddressValid(FileObject->SectionObjectPointer))
    135     {
    136         ImageSectionObject = FileObject->SectionObjectPointer->ImageSectionObject;
    137         DataSectionObject = FileObject->SectionObjectPointer->DataSectionObject;
    138         SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
    139         
    140         FileObject->SectionObjectPointer->ImageSectionObject = NULL;
    141         FileObject->SectionObjectPointer->DataSectionObject = NULL;
    142         FileObject->SectionObjectPointer->SharedCacheMap = NULL;
    143     }
    144 
    145 
    146 
    147 
    148     IoSetCompletionRoutine(Irp,IrpCompleteRoutine,&hEvent,TRUE,TRUE,TRUE);
    149 
    150 
    151     IoCallDriver(DeviceObject,Irp);
    152 
    153     KeWaitForSingleObject(&hEvent,Executive,KernelMode,TRUE,NULL);
    154 
    155 
    156 
    157 
    158     //恢复环境
    159     if (MmIsAddressValid(FileObject->SectionObjectPointer))
    160     {    
    161         FileObject->SectionObjectPointer->ImageSectionObject = ImageSectionObject;
    162         FileObject->SectionObjectPointer->DataSectionObject = DataSectionObject;
    163         FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap;    
    164     }
    165 
    166 
    167 
    168     ObDereferenceObject(FileObject);
    169 }
    170 
    171 
    172 
    173 BOOLEAN
    174 SKillStripFileAttributes(HANDLE  hFile)
    175 {
    176     NTSTATUS          Status = STATUS_SUCCESS;
    177     PFILE_OBJECT      FileObject;
    178     PDEVICE_OBJECT    DeviceObject;
    179     PIRP              Irp;
    180     KEVENT            kEvent;
    181     FILE_BASIC_INFORMATION    FileBaseInfor;
    182     IO_STATUS_BLOCK Iosb;
    183     PIO_STACK_LOCATION IrpSp;
    184     
    185     BOOLEAN bInit = FALSE;
    186     
    187     
    188     
    189     Status = ObReferenceObjectByHandle(hFile,
    190         DELETE,
    191         *IoFileObjectType,
    192         KernelMode,
    193         &FileObject,
    194         NULL);
    195     
    196     if (!NT_SUCCESS(Status))
    197     {
    198         return FALSE;
    199     }
    200     
    201     DeviceObject = IoGetRelatedDeviceObject(FileObject);  //VPB->DeviceObject
    202     Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
    203     
    204     if (Irp == NULL)
    205     {
    206         ObDereferenceObject(FileObject);
    207         return FALSE;
    208     }
    209     
    210     KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
    211     
    212     memset(&FileBaseInfor,0,sizeof(FILE_BASIC_INFORMATION));
    213     
    214     FileBaseInfor.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    215     Irp->AssociatedIrp.SystemBuffer = &FileBaseInfor;
    216     Irp->UserEvent = &kEvent;
    217     Irp->UserIosb = &Iosb;
    218     Irp->Tail.Overlay.OriginalFileObject = FileObject;
    219     Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
    220     Irp->RequestorMode = KernelMode;
    221     
    222     IrpSp = IoGetNextIrpStackLocation(Irp);
    223     IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
    224     IrpSp->DeviceObject = DeviceObject;
    225     IrpSp->FileObject = FileObject;
    226     IrpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION);
    227     IrpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
    228     
    229     
    230     IoSetCompletionRoutine(
    231         Irp,
    232         IrpCompleteRoutine,
    233         &kEvent,
    234         TRUE,
    235         TRUE,
    236         TRUE);
    237     
    238     IoCallDriver(DeviceObject,Irp);
    239     KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);
    240     ObDereferenceObject(FileObject);
    241     
    242     return TRUE;
    243 }
    244 
    245 
    246 
    247 NTSTATUS
    248 IrpCompleteRoutine(PDEVICE_OBJECT  DeviceObject,PIRP  Irp,PVOID Context)
    249 {
    250     KeSetEvent(Irp->UserEvent,IO_NO_INCREMENT,FALSE);
    251     
    252     IoFreeIrp(Irp);
    253     
    254     return STATUS_MORE_PROCESSING_REQUIRED;
    255     
    256 }
  • 相关阅读:
    四色定理+dfs(poj 1129)
    栈的应用:表达式求值运算
    多重背包 (poj 1014)
    poj 1080 (LCS变形)
    KMP算法(快速模式匹配)
    贪心+构造( Codeforces Round #344 (Div. 2))
    JavaScript Ajax
    Canvas绘图
    TCP/IP协议
    移动端click事件延迟300ms到底是怎么回事,该如何解决?
  • 原文地址:https://www.cnblogs.com/zibility/p/5402597.html
Copyright © 2011-2022 走看看