阅读:3591回复:1
使用IRP进行文件操作#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; } |
|
沙发#
发布于:2009-09-04 13:17
感谢分享
|
|
|