使用IRP进行文件操作
使用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进行文件操作的更多相关文章
- Windows xp 重载内核(使用Irp进行文件操作)
一.前言 最近在阅读A盾代码A盾电脑防护(原名 3600safe)anti-rootkit开放源代码,有兴趣的可以去看雪论坛下载,本文代码摘自其中的重载内核. 二.实现步骤 1.ZwQuerySyst ...
- 【.NET深呼吸】Zip文件操作(1):创建和读取zip文档
.net的IO操作支持对zip文件的创建.读写和更新.使用起来也比较简单,.net的一向作风,东西都准备好了,至于如何使用,请看着办. 要对zip文件进行操作,主要用到以下三个类: 1.ZipFile ...
- 野路子出身PowerShell 文件操作实用功能
本文出处:http://www.cnblogs.com/wy123/p/6129498.html 因工作需要,处理一批文件,本想写C#来处理的,后来想想这个是PowerShell的天职,索性就网上各种 ...
- Node基础篇(文件操作)
文件操作 相关模块 Node内核提供了很多与文件操作相关的模块,每个模块都提供了一些最基本的操作API,在NPM中也有社区提供的功能包 fs: 基础的文件操作 API path: 提供和路径相关的操作 ...
- 归档NSKeyedArchiver解归档NSKeyedUnarchiver与文件管理类NSFileManager (文件操作)
========================== 文件操作 ========================== 一.归档NSKeyedArchiver 1.第一种方式:存储一种数据. // 归档 ...
- SQL Server附加数据库报错:无法打开物理文件,操作系统错误5
问题描述: 附加数据时,提示无法打开物理文件,操作系统错误5.如下图: 问题原因:可能是文件访问权限方面的问题. 解决方案:找到数据库的mdf和ldf文件,赋予权限即可.如下图: 找到mdf ...
- 通过cmd完成FTP上传文件操作
一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...
- Linux文件操作的主要接口API及相关细节
操作系统API: 1.API是一些函数,这些函数是由linux系统提供支持的,由应用层程序来使用,应用层程序通过调用API来调用操作系统中的各种功能,来干活 文件操作的一般步骤: 1.在linux系统 ...
- C语言的fopen函数(文件操作/读写)
头文件:#include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * path, c ...
随机推荐
- 程序员带你学习安卓开发-XML文档的创建与解析
这是程序员带你学习安卓开发系列教程.本文章致力于面向对象程序员可以快速学习开发安卓技术. 上篇文章:程序员带你学习安卓开发系列-Android文件存储 因知识连贯性推荐关注头条号:做全栈攻城狮.从头开 ...
- Apache 80 端口被占用无法重启解决办法
原文出处 Apache 80 端口被占用无法重启解决办法 www.111cn.net 编辑:tiger 来源:转载使用WEB服务器的朋友都知道80端口是一个用来对外让用户访问的一个端口了,像apach ...
- .Net之美读书系列(一):委托与事件
开启新的读书之旅,这次读的书为<.Net之美:.Net关键技术深入解析>. 我是选择性阅读的,把一些自己觉得容易忘记的,或者比较重要的知识点记录下来,以便以后能方便呢查阅. 尊重书本原作者 ...
- ActiveMQ系列(1) - 使用入门
没网的日子真的不好过啊 1.背景: 对于常见业务中,数据并发是一个很头疼的问题,很多时候,会出现资源共享导致线程阻塞的问题,这时候问题就来了,,,老板也尾随来了,来 ...
- python中关于正则表达式三
2015年8月14日 11:10 7.2正则表达式操作 正则表达式使用反斜杠字符'\'来暗示一些特殊的形式或者允许特殊的字符使用但是没有调用它们特殊的意思.在字符串常量中的相同目标的字符的python ...
- EditText属性详解
关于EditText属性详解很详细的记录,转过来收着 1.EditText输入的文字为密码形式的设置 (1)通过.xml里设置: 把该EditText设为:android:password=" ...
- SQL Server调优系列基础篇 - 索引运算总结
前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方 ...
- DOS 全集
DOS全集 winver 检查Windows版本 wmimgmt.msc 打开Windows管理体系结构(wmi) wupdmgr Windows更新程序 wscript Windows脚本宿主 ...
- 使用反射让Spinner选择同一选项时触发onItemSelected事件
翻看源码,Spinner判断是否触发onItemSelected,是在它的基类AdapterView里面做的: void checkSelectionChanged() { if ((mSelecte ...
- Java并发编程:进程和线程之由来__进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能
转载自海子:http://www.cnblogs.com/dolphin0520/p/3910667.html Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨 ...