使用IRP进行文件操作

首先声明这个是菜鸟—我的学习日记,不是什么高深文章,高手们慎看.

一定要先感谢为技术的进步而付出辛勤汗水的人,感谢他们对技术的共享.

一个通用IRP访问文件的十六进制编辑器(开源代码)     --   被诅咒的神(邪恶八进制信息安全团队)

Windows平台内核级文件访问                               --   baiyuanfan (baiyuanfan@163.com)

特别感谢被诅咒的神,他写的<ExTools v1.2>里面包含了非常多IRP对文件操作的宝贵信息,对初入门的我来说帮助非常大.大家可以去下载他的源码参考.

虽然天气仍然好冻,但文章是不写不快,刚做好了一些函数,希望共享出来之后对大家有小小帮助.这个月是放假,时间比较充裕,利用这些时间可以学好多知识.很久以前就对pjf写的IceSword感兴趣,也很羡慕他能够写出这么强大的Anti-Rootkit软件,如今终于实现类似他那样文件操作的功能,好开心.(我也不敢确定他是这样写的,网上看到他是用IRP对文件操作的).

我写这些函数的过程好曲折,幸好我没放弃,我先是看了<Windows文件系统过滤驱动开发教程(第二版)-- 楚狂人>,没看完,自己总结:就是将自己的驱动绑定在设备栈的栈顶,让所有IRP都经过自己的驱动,对IRP过滤,其中细节非常多,如果不是楚狂人做了这么好的说明教程,光看微软给的例子可能就没那么容易了,所以要感谢楚狂人.但对自己发送IRP帮助不大.再而看了OSR_docs里面的pdf,也不是全看,看了一些关键的,例如<IrpMan.pdf>里面的<2.2.14.6 Kernel File Copy Example>,这里面写了4个IRP的使用,分别为IRP_MJ_QUERY_INFORMATION  IRP_MJ_SET_INFORMATION  IRP_MJ_READ  IRP_MJ_WRITE,建议大家也去看看,是非常好的参考资料.但这里没有写到IRP_MJ_CREATE的填写,于是我参考着这些资料填写IRP然后IoCallDriver,当然不成功拉.于是我跳过它先做IRP_MJ_DIRECTORY_CONTROL的,也就是平时枚举文件用的NtQueryDirectoryFile最终要发送的IRP,成功了,那时好开心.接下来在网上发现了被诅咒的神写的<ExTools v1.2>的源码,有这么好的参考资料,进度当然快好多啦.而<ExTools v1.2>没的IRP_MJ_SET_INFORMATION也帮您补上了^_^.现在完成了将成品共享给大家.

这里有个重点,我引用<Windows平台内核级文件访问>里面的一段话:

文件系统过滤驱动Attach在正常的文件系统之上,监视和过滤我们的文件访问。文件系统驱动栈就是由这一连串的Attach起来的过滤驱动组成。我们可以用IoGetRelatedDeviceObject这个函数来获得一个FileObject对应的最底层的那个功能驱动对象(FDO)。但是这样虽然绕过了那些过滤驱动,却同时也绕过了正常的FSD如Ntfs/Fastfat,因为正常的FSD也是作为一个过滤驱动存在的。磁盘文件对象的对应的最底层的FDO是Ftdisk.sys,它已经因为过于底层而不能处理我们投递的IRP请求。
   其实正常的FSD信息存储在一个Vpb结构中,我们可以使用IoGetBaseFileSystemDeviceObject这个未公开的内核函数来得到它。它就是我们发送IRP的目标了。

但既然是在Vpb里面有正常的FSD,我就直接用了,以免调用了被hook的函数.知道文件过滤驱动原理就可以知道这样做可以绕过栈顶的驱动直接发送IRP到正常FSD.这点很重要.

我写的大概有如下一些IRP的调用,及其所对应的函数我也列出来,好让像我这样的初学者明白.(其实这里大部分都不是我写的^_^)

IRP_MJ_CREATE

NtCreateFile

创建或新建文件返回句柄,不过发IRP返回的是FILE_OBJECT,线程无关的.

IRP_MJ_CLEANUP

NtClose

用于关闭HANDLE的

IRP_MJ_CLOSE

ObDereferenceObject

用于关闭FILE_OBJECT的

IRP_MJ_DIRECTORY_CONTROL

NtQueryDirectoryFile

枚举目录,好多时候都被hook的

IRP_MJ_QUERY_INFORMATION

NtQueryInformationFile

取得文件信息

IRP_MJ_SET_INFORMATION

NtSetInformationFile

设置文件信息:删除,改名,改属性

IRP_MJ_READ

NtReadFile

读文件

IRP_MJ_WRITE

NtWriteFile

写文件

直接发送IRP对文件进行操作是可以避免一些Rootkit的干扰的,除非Hook IoCallDriver,不过我在网上看到pjf写的IceSword是要先读取ntkrnlpa.exe(多核处理器使用)或者ntoskrnl.exe(单核处理器使用)里面的IoCallDriver的开头几字节然后还原一下,防止被hook.啊~pjf想得真周到,羡慕~~~~~(哪天我能有他那么强咧^_^).好啦,以下是代码了,代码比较长,参数比较复杂,一个细节写错可能会BSOD.我已经尽量依照好似微软给的API那样写的了,有说明(其实是复制WDK的^_^),再一次声明代码大部分不是我写的,我不过是改了点,更方便大家使用习惯,从中我也学了不少,唉,中国这些技术的文章真少,是落后?

如果发现这里面的函数调用会产生蓝屏,而确认您的传入参数准确无误,那么请在这里留言给我,谢谢.

#include "ntifs.h"

//

//  Define the structure used by this driver module.

//

typedef struct _AUX_ACCESS_DATA {

PPRIVILEGE_SET PrivilegesUsed;

GENERIC_MAPPING GenericMapping;

ACCESS_MASK AccessesToAudit;

ULONG Reserve;                            //unknow...

} AUX_ACCESS_DATA, *PAUX_ACCESS_DATA;

//

//  Define the local routines used by this driver module.

//

NTSTATUS

ObCreateObject (

IN KPROCESSOR_MODE ProbeMode,

IN POBJECT_TYPE ObjectType,

IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

IN KPROCESSOR_MODE OwnershipMode,

IN OUT PVOID ParseContext OPTIONAL,

IN ULONG ObjectBodySize,

IN ULONG PagedPoolCharge,

IN ULONG NonPagedPoolCharge,

OUT PVOID *Object

);

NTSTATUS

SeCreateAccessState(

IN PACCESS_STATE AccessState,

IN PAUX_ACCESS_DATA AuxData,

IN ACCESS_MASK DesiredAccess,

IN PGENERIC_MAPPING GenericMapping OPTIONAL

);

//

// IoCompletionRoutine

//

// This routine is used to handle I/O (read OR write) completion

//

// Inputs:

// DeviceObject - not used

// Irp - the I/O operation being completed

// Context - not used

//

// Outputs:

// None.

//

// Returns:

// STATUS_MORE_PROCESSING_REQUIRED

//

// Notes:

// The purpose of this routine is to do "cleanup" on I/O operations

// so we don't constantly throw away perfectly good MDLs as part of

// completion processing.

//

NTSTATUS

IoCompletionRoutine(

IN PDEVICE_OBJECT DeviceObject,

IN PIRP Irp,

IN PVOID Context

);

//

// IrpCreateFile

//

// This routine is used as NtCreateFile but first and third parameter.

//

// Inputs:

// DesiredAccess - Specifies an ACCESS_MASK value that determines

//                     the requested access to the object.

// FilePath - Path of file to create,as L"C://Windows"(Unicode).

// AllocationSize - Pointer to a LARGE_INTEGER that contains the initial allocation

//                     size, in bytes, for a file that is created or overwritten.

// FileAttributes - Specifies one or more FILE_ATTRIBUTE_XXX flags, which represent

//                     the file attributes to set if you are creating or overwriting a file.

// ShareAccess - Type of share access.

// CreateDisposition - Specifies the action to perform if the file does or does not exist.

// CreateOptions - Specifies the options to apply when creating or opening the file.

// EaBuffer - For device and intermediate drivers, this parameter must be a NULL pointer.

// EaLength - For device and intermediate drivers, this parameter must be zero.

//

// Ouputs:

// FileObject - Pointer to a PFILE_OBJECT variable that

//                 receives a PFILE_OBJECT to the file.

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtCreateFile,but return FILE_OBJECT not HANDLE.

//

NTSTATUS

IrpCreateFile(

OUT PFILE_OBJECT  *FileObject,

IN ACCESS_MASK  DesiredAccess,

IN PUNICODE_STRING  FilePath,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PLARGE_INTEGER  AllocationSize OPTIONAL,

IN ULONG  FileAttributes,

IN ULONG  ShareAccess,

IN ULONG  CreateDisposition,

IN ULONG  CreateOptions,

IN PVOID  EaBuffer OPTIONAL,

IN ULONG  EaLength

);

//

// IrpClose

//

// This routine is used as ObDereferenceObject.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT variable that will close

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to ObDereferenceObject

//

NTSTATUS

IrpClose(

IN PFILE_OBJECT  FileObject

);

//

// IrpQueryDirectoryFile

//

// This routine is used as NtQueryDirectoryFile.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT.

// Length - Size, in bytes, of the buffer pointed to by FileInformation. The caller

//            should set this parameter according to the given FileInformationClass.

// FileInformationClass - Type of information to be returned about files in the directory.

// FileName - Pointer to a caller-allocated Unicode string containing the name of a file

//            (or multiple files, if wildcards are used) within the directory specified by FileHandle.

//            This parameter is optional and can be NULL.

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

// FileInformation - Pointer to a buffer that receives the desired

//                          information about the file.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtQueryDirectoryFile, but no ApcRoutine.

//

NTSTATUS

IrpQueryDirectoryFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN PUNICODE_STRING  FileName  OPTIONAL

);

//

// IrpQueryInformationFile

//

// This routine is used as NtQueryInformationFile.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT.

// Length - Size, in bytes, of the buffer pointed to by FileInformation. The caller

//            should set this parameter according to the given FileInformationClass.

// FileInformationClass - Type of information to be returned about files in the directory.

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

// FileInformation - Pointer to a buffer that receives the desired

//                          information about the file.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtQueryInformationFile.

//

NTSTATUS

IrpQueryInformationFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass

);

//

// IrpSetInformationFile

//

// This routine is used as NtSetInformationFile.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT.

// FileInformation - Pointer to a buffer that contains the information to set for the file.

// Length - Size, in bytes, of the buffer pointed to by FileInformation. The caller

//            should set this parameter according to the given FileInformationClass.

// FileInformationClass - Type of information to be returned about files in the directory.

// ReplaceIfExists - Set to TRUE to specify that if a file with the same name already exists,

//                     it should be replaced with the given file. Set to FALSE if the rename

//                     operation should fail if a file with the given name already exists.

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtSetInformationFile.

//

NTSTATUS

IrpSetInformationFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN BOOLEAN  ReplaceIfExists

);

//

// IrpReadFile

//

// This routine is used as NtReadFile.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT.

// Buffer - Pointer to a caller-allocated buffer that receives the data read from the file.

// Length - The size, in bytes, of the buffer pointed to by Buffer.

// ByteOffset - Pointer to a variable that specifies the starting byte offset

//                 in the file where the read operation will begin.

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                completion status and information about the requested read operation.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtReadFile, but no ApcRoutine.

//

NTSTATUS

IrpReadFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  Buffer,

IN ULONG  Length,

IN PLARGE_INTEGER  ByteOffset  OPTIONAL

);

//

// IrpReadFile

//

// This routine is used as NtReadFile.

//

// Inputs:

// FileObject - Pointer to a PFILE_OBJECT.

// Buffer - Pointer to a caller-allocated buffer that contains the data to write to the file.

// Length - The size, in bytes, of the buffer pointed to by Buffer.

// ByteOffset - Pointer to a variable that specifies the starting byte offset

//                 in the file for beginning the write operation.

//

// Ouputs:

// IoStatusBlock - Pointer to an IO_STATUS_BLOCK structure that receives the final

//                 completion status and information about the requested read operation.

//

// Returns:

// The IRP send status.

//

// Notes:

// This is equivalent to NtReadFile, but no ApcRoutine.

//

NTSTATUS

IrpWriteFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PVOID  Buffer,

IN ULONG  Length,

IN PLARGE_INTEGER  ByteOffset  OPTIONAL

);

//

// Function start.

//

NTSTATUS

IoCompletionRoutine(

IN PDEVICE_OBJECT DeviceObject,

IN PIRP Irp,

IN PVOID Context)

{

*Irp->UserIosb = Irp->IoStatus;

if (Irp->UserEvent)

KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0);

if (Irp->MdlAddress)

{

IoFreeMdl(Irp->MdlAddress);

Irp->MdlAddress = NULL;

}

IoFreeIrp(Irp);

return STATUS_MORE_PROCESSING_REQUIRED;

}

NTSTATUS

IrpCreateFile(

OUT PFILE_OBJECT  *FileObject,

IN ACCESS_MASK  DesiredAccess,

IN PUNICODE_STRING  FilePath,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PLARGE_INTEGER  AllocationSize  OPTIONAL,

IN ULONG  FileAttributes,

IN ULONG  ShareAccess,

IN ULONG  CreateDisposition,

IN ULONG  CreateOptions,

IN PVOID  EaBuffer  OPTIONAL,

IN ULONG  EaLength)

{

NTSTATUS ntStatus;

HANDLE hFile;

PFILE_OBJECT pFile, _FileObject;

UNICODE_STRING UniDeviceNameString;

OBJECT_ATTRIBUTES ObjectAttributes;

PDEVICE_OBJECT DeviceObject, RealDevice;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

ACCESS_STATE AccessState;

AUX_ACCESS_DATA AuxData;

IO_SECURITY_CONTEXT SecurityContext;

if(FilePath->Length < 6)

return STATUS_INVALID_PARAMETER;

RtlInitUnicodeString( &UniDeviceNameString, L"//DosDevices//*://" );

UniDeviceNameString.Buffer[12] = FilePath->Buffer[0];

InitializeObjectAttributes(&ObjectAttributes, &UniDeviceNameString, OBJ_KERNEL_HANDLE, NULL, NULL);

ntStatus = IoCreateFile(&hFile,

GENERIC_READ|SYNCHRONIZE,

&ObjectAttributes,

IoStatusBlock,

NULL,

FILE_ATTRIBUTE_NORMAL,

FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,

FILE_OPEN,

FILE_SYNCHRONOUS_IO_NONALERT,

NULL,

0,

CreateFileTypeNone,

NULL,

IO_NO_PARAMETER_CHECKING);

if(!NT_SUCCESS(ntStatus)) return ntStatus;

ntStatus = ObReferenceObjectByHandle(hFile,

FILE_READ_ACCESS, // ACCESS_MASK

*IoFileObjectType,

KernelMode,

&pFile,

0);

NtClose(hFile);

if(!NT_SUCCESS(ntStatus)) return ntStatus;

DeviceObject = pFile->Vpb->DeviceObject;

RealDevice = pFile->Vpb->RealDevice;

ObDereferenceObject(pFile);

InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_CASE_INSENSITIVE, 0, NULL);

ntStatus = ObCreateObject(KernelMode,

*IoFileObjectType,

&ObjectAttributes,

KernelMode,

NULL,

sizeof(FILE_OBJECT),

0,

0,

&_FileObject);

if (!NT_SUCCESS(ntStatus)) return ntStatus;

Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

if(Irp == NULL)

{

ObDereferenceObject(_FileObject);

return STATUS_INSUFFICIENT_RESOURCES;

}

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

RtlZeroMemory(_FileObject, sizeof(FILE_OBJECT));

_FileObject->Type = IO_TYPE_FILE;

_FileObject->Size = sizeof(FILE_OBJECT);

_FileObject->DeviceObject = RealDevice;

_FileObject->Flags = FO_SYNCHRONOUS_IO;

RtlInitUnicodeString( &_FileObject->FileName, &FilePath->Buffer[2]);

KeInitializeEvent(&_FileObject->Lock, SynchronizationEvent, FALSE);

KeInitializeEvent(&_FileObject->Event, NotificationEvent, FALSE);

RtlZeroMemory(&AuxData, sizeof(AUX_ACCESS_DATA));

ntStatus = SeCreateAccessState( &AccessState,

&AuxData,

DesiredAccess,

IoGetFileObjectGenericMapping());

if (!NT_SUCCESS(ntStatus))

{

IoFreeIrp(Irp);

ObDereferenceObject(_FileObject);

return ntStatus;

}

SecurityContext.SecurityQos = NULL;

SecurityContext.AccessState = &AccessState;

SecurityContext.DesiredAccess = DesiredAccess;

SecurityContext.FullCreateOptions = 0;

Irp->MdlAddress = NULL;

Irp->AssociatedIrp.SystemBuffer = EaBuffer;

Irp->Flags = IRP_CREATE_OPERATION|IRP_SYNCHRONOUS_API;

Irp->RequestorMode = KernelMode;

Irp->UserIosb = IoStatusBlock;

Irp->UserEvent = &kEvent;

Irp->PendingReturned = FALSE;

Irp->Cancel = FALSE;

Irp->CancelRoutine = NULL;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.AuxiliaryBuffer = NULL;

Irp->Tail.Overlay.OriginalFileObject = _FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_CREATE;

IrpSp->DeviceObject = DeviceObject;

IrpSp->FileObject = _FileObject;

IrpSp->Parameters.Create.SecurityContext = &SecurityContext;

IrpSp->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions;

IrpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes;

IrpSp->Parameters.Create.ShareAccess = (USHORT)ShareAccess;

IrpSp->Parameters.Create.EaLength = EaLength;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(DeviceObject, Irp);

if(ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);

ntStatus = IoStatusBlock->Status;

if(!NT_SUCCESS(ntStatus))

{

_FileObject->DeviceObject = NULL;

ObDereferenceObject(_FileObject);

}

else

{

InterlockedIncrement(&_FileObject->DeviceObject->ReferenceCount);

if (_FileObject->Vpb)

InterlockedIncrement(&_FileObject->Vpb->ReferenceCount);

*FileObject = _FileObject;

}

return ntStatus;

}

NTSTATUS

IrpClose(

IN PFILE_OBJECT  FileObject)

{

NTSTATUS ntStatus;

IO_STATUS_BLOCK  IoStatusBlock;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

PDEVICE_OBJECT pBaseDeviceObject = FileObject->Vpb->DeviceObject;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

Irp->UserEvent = &kEvent;

Irp->UserIosb = &IoStatusBlock;

Irp->RequestorMode = KernelMode;

Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_CLEANUP;

IrpSp->FileObject = FileObject;

ntStatus = IoCallDriver(pBaseDeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);

ntStatus = IoStatusBlock.Status;

if(!NT_SUCCESS(ntStatus))

{

IoFreeIrp(Irp);

return ntStatus;

}

KeClearEvent(&kEvent);

IoReuseIrp(Irp , STATUS_SUCCESS);

Irp->UserEvent = &kEvent;

Irp->UserIosb = &IoStatusBlock;

Irp->Tail.Overlay.OriginalFileObject = FileObject;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->AssociatedIrp.SystemBuffer = (PVOID)NULL;

Irp->Flags = IRP_CLOSE_OPERATION|IRP_SYNCHRONOUS_API;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_CLOSE;

IrpSp->FileObject = FileObject;

if (FileObject->Vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))

{

InterlockedDecrement(&FileObject->Vpb->ReferenceCount);

FileObject->Flags |= FO_FILE_OPEN_CANCELLED;

}

ntStatus = IoCallDriver(pBaseDeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);

IoFreeIrp(Irp);

ntStatus = IoStatusBlock.Status;

return ntStatus;

}

NTSTATUS

IrpQueryDirectoryFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN PUNICODE_STRING  FileName  OPTIONAL)

{

NTSTATUS ntStatus;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

RtlZeroMemory(FileInformation, Length);

Irp->UserEvent = &kEvent;

Irp->UserIosb = IoStatusBlock;

Irp->UserBuffer = FileInformation;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

Irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;

IrpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;

IrpSp->FileObject = FileObject;

IrpSp->Flags = SL_RESTART_SCAN;

IrpSp->Parameters.QueryDirectory.Length = Length;

IrpSp->Parameters.QueryDirectory.FileName = FileName;

IrpSp->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(FileObject->Vpb->DeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);

return IoStatusBlock->Status;

}

NTSTATUS

IrpQueryInformationFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass)

{

NTSTATUS ntStatus;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

RtlZeroMemory(FileInformation, Length);

Irp->AssociatedIrp.SystemBuffer = FileInformation;

Irp->UserEvent = &kEvent;

Irp->UserIosb = IoStatusBlock;

Irp->RequestorMode = KernelMode;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION;

IrpSp->DeviceObject = FileObject->Vpb->DeviceObject;

IrpSp->FileObject = FileObject;

IrpSp->Parameters.QueryFile.Length = Length;

IrpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(FileObject->Vpb->DeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);

return IoStatusBlock->Status;

}

NTSTATUS

IrpSetInformationFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PVOID  FileInformation,

IN ULONG  Length,

IN FILE_INFORMATION_CLASS  FileInformationClass,

IN BOOLEAN  ReplaceIfExists)

{

NTSTATUS ntStatus;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

Irp->AssociatedIrp.SystemBuffer = FileInformation;

Irp->UserEvent = &kEvent;

Irp->UserIosb = IoStatusBlock;

Irp->RequestorMode = KernelMode;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;

IrpSp->DeviceObject = FileObject->Vpb->DeviceObject;

IrpSp->FileObject = FileObject;

IrpSp->Parameters.SetFile.ReplaceIfExists = ReplaceIfExists;

IrpSp->Parameters.SetFile.FileObject = FileObject;

IrpSp->Parameters.SetFile.AdvanceOnly = FALSE;

IrpSp->Parameters.SetFile.Length = Length;

IrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(FileObject->Vpb->DeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);

return IoStatusBlock->Status;

}

NTSTATUS

IrpReadFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

OUT PVOID  Buffer,

IN ULONG  Length,

IN PLARGE_INTEGER  ByteOffset  OPTIONAL)

{

NTSTATUS ntStatus;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

if(ByteOffset == NULL)

{

if(!(FileObject->Flags & FO_SYNCHRONOUS_IO))

return STATUS_INVALID_PARAMETER;

ByteOffset = &FileObject->CurrentByteOffset;

}

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if(Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

RtlZeroMemory(Buffer, Length);

if(FileObject->DeviceObject->Flags & DO_BUFFERED_IO)

{

Irp->AssociatedIrp.SystemBuffer = Buffer;

}

else if(FileObject->DeviceObject->Flags & DO_DIRECT_IO)

{

Irp->MdlAddress = IoAllocateMdl(Buffer, Length, 0, 0, 0);

if (Irp->MdlAddress == NULL)

{

IoFreeIrp(Irp);

return STATUS_INSUFFICIENT_RESOURCES;

}

MmBuildMdlForNonPagedPool(Irp->MdlAddress);

}

else

{

Irp->UserBuffer = Buffer;

}

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

Irp->UserEvent = &kEvent;

Irp->UserIosb = IoStatusBlock;

Irp->RequestorMode = KernelMode;

Irp->Flags = IRP_READ_OPERATION;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_READ;

IrpSp->MinorFunction = IRP_MN_NORMAL;

IrpSp->DeviceObject = FileObject->Vpb->DeviceObject;

IrpSp->FileObject = FileObject;

IrpSp->Parameters.Read.Length = Length;

IrpSp->Parameters.Read.ByteOffset = *ByteOffset;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(FileObject->Vpb->DeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, 0);

return IoStatusBlock->Status;

}

NTSTATUS

IrpWriteFile(

IN PFILE_OBJECT  FileObject,

OUT PIO_STATUS_BLOCK  IoStatusBlock,

IN PVOID  Buffer,

IN ULONG  Length,

IN PLARGE_INTEGER  ByteOffset  OPTIONAL)

{

NTSTATUS ntStatus;

PIRP Irp;

KEVENT kEvent;

PIO_STACK_LOCATION IrpSp;

if (FileObject->Vpb == 0 || FileObject->Vpb->DeviceObject == NULL)

return STATUS_UNSUCCESSFUL;

if (ByteOffset == NULL)

{

if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))

return STATUS_INVALID_PARAMETER;

ByteOffset = &FileObject->CurrentByteOffset;

}

Irp = IoAllocateIrp(FileObject->Vpb->DeviceObject->StackSize, FALSE);

if (Irp == NULL) return STATUS_INSUFFICIENT_RESOURCES;

if(FileObject->DeviceObject->Flags & DO_BUFFERED_IO)

{

Irp->AssociatedIrp.SystemBuffer = Buffer;

}

else

{

Irp->MdlAddress = IoAllocateMdl(Buffer, Length, 0, 0, 0);

if (Irp->MdlAddress == NULL)

{

IoFreeIrp(Irp);

return STATUS_INSUFFICIENT_RESOURCES;

}

MmBuildMdlForNonPagedPool(Irp->MdlAddress);

}

KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);

Irp->UserEvent = &kEvent;

Irp->UserIosb = IoStatusBlock;

Irp->RequestorMode = KernelMode;

Irp->Flags = IRP_WRITE_OPERATION;

Irp->Tail.Overlay.Thread = PsGetCurrentThread();

Irp->Tail.Overlay.OriginalFileObject = FileObject;

IrpSp = IoGetNextIrpStackLocation(Irp);

IrpSp->MajorFunction = IRP_MJ_WRITE;

IrpSp->MinorFunction = IRP_MN_NORMAL;

IrpSp->DeviceObject = FileObject->Vpb->DeviceObject;

IrpSp->FileObject = FileObject;

IrpSp->Parameters.Write.Length = Length;

IrpSp->Parameters.Write.ByteOffset = *ByteOffset;

IoSetCompletionRoutine(Irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE);

ntStatus = IoCallDriver(FileObject->Vpb->DeviceObject, Irp);

if (ntStatus == STATUS_PENDING)

KeWaitForSingleObject(&kEvent, Executive, KernelMode, TRUE, NULL);

return IoStatusBlock->Status;

}

http://blog.csdn.net/cooblily/article/details/2080822

使用IRP进行文件操作的更多相关文章

  1. Windows xp 重载内核(使用Irp进行文件操作)

    一.前言 最近在阅读A盾代码A盾电脑防护(原名 3600safe)anti-rootkit开放源代码,有兴趣的可以去看雪论坛下载,本文代码摘自其中的重载内核. 二.实现步骤 1.ZwQuerySyst ...

  2. 【.NET深呼吸】Zip文件操作(1):创建和读取zip文档

    .net的IO操作支持对zip文件的创建.读写和更新.使用起来也比较简单,.net的一向作风,东西都准备好了,至于如何使用,请看着办. 要对zip文件进行操作,主要用到以下三个类: 1.ZipFile ...

  3. 野路子出身PowerShell 文件操作实用功能

    本文出处:http://www.cnblogs.com/wy123/p/6129498.html 因工作需要,处理一批文件,本想写C#来处理的,后来想想这个是PowerShell的天职,索性就网上各种 ...

  4. Node基础篇(文件操作)

    文件操作 相关模块 Node内核提供了很多与文件操作相关的模块,每个模块都提供了一些最基本的操作API,在NPM中也有社区提供的功能包 fs: 基础的文件操作 API path: 提供和路径相关的操作 ...

  5. 归档NSKeyedArchiver解归档NSKeyedUnarchiver与文件管理类NSFileManager (文件操作)

    ========================== 文件操作 ========================== 一.归档NSKeyedArchiver 1.第一种方式:存储一种数据. // 归档 ...

  6. SQL Server附加数据库报错:无法打开物理文件,操作系统错误5

    问题描述:      附加数据时,提示无法打开物理文件,操作系统错误5.如下图: 问题原因:可能是文件访问权限方面的问题. 解决方案:找到数据库的mdf和ldf文件,赋予权限即可.如下图: 找到mdf ...

  7. 通过cmd完成FTP上传文件操作

    一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...

  8. Linux文件操作的主要接口API及相关细节

    操作系统API: 1.API是一些函数,这些函数是由linux系统提供支持的,由应用层程序来使用,应用层程序通过调用API来调用操作系统中的各种功能,来干活 文件操作的一般步骤: 1.在linux系统 ...

  9. C语言的fopen函数(文件操作/读写)

    头文件:#include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为:    FILE * fopen(const char * path, c ...

随机推荐

  1. oracle数据库没有监听服务与实例服务(OracleServicesXX)的解决方法

    不知道为什么,可能是因为更新系统的原因,过了一段时间,想打开oracle服务,发现居然没有任何oracle有关的服务了,但以前的数据库文件什么的都在,心想肯定是可以复原的,应该只是注册表的问题罢了.在 ...

  2. Android 抽屉效果

    昨天在用“酷我音乐”听歌的时候注意到了界面右上角的四角方块,当我点击这个方块的时候会从屏幕的左边弹出新的界面而把原来的界面挤到左边,是显示了一小部分. 于是,我便在网上查询了一下相关的文章,现将这种效 ...

  3. SQL Server 事务与锁

    了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁: ...

  4. tomcat启动正常,404. Eclipse没有正确部署工程项目

    http://blog.csdn.net/lynn_wgr/article/details/7751228 在eclipse中新建的Dynamic Web Project.写好代码后,选择Run on ...

  5. sql 常用操作脚本代码

    ,--运行fy_mh库[use] use fy_mh ,--查询 mh_dblj表 select * from mh_dblj ,--更新 某个字段(把表的某个字段下的所有的数据清空)[update ...

  6. rc4加密

    function RC4(Expression, Password: string): string; var RB : array[0..255] of Integer; X, Y, Z: long ...

  7. 关于C++对汉字拼音的处理(2)

    对于前面获取字符串汉字全拼音的功能,大家应该有个了解了.现在我又综合广大网友流传的获取字符串汉字拼音首字母的功能进行了整理.介绍如下 这个功能写的稍微有点复杂 使用3个函数解决了获取字符串汉字首拼音串 ...

  8. 身份证js验证

    <script type="text/javascript"> //--身份证号码验证-支持新的带x身份证 function isIdCardNo(num) { var ...

  9. think ajax 应用

    首先得引入 jquery 文件,另外定义一个处理的 js.js 文件 如实现用 post 传输方法: 模板文件: <script type="text/javascript" ...

  10. php计算最后一次,第一次字符串出现位置

    strpos($str, n) 首次,n在str第一次出现位置, strrpos($str, n) 最后一次,n在str最后一次出现位置 strripos区分大小写