After building the IRP to write the file, the file size will not change

Hi,Driver experts.Help! I am working for a volume filtering.I am build a IRP to write file,but ,I find the file size is not change.then ,I also build the IRP to write the file on other volume device,still failed to change the file size.
codes like as

NTSTATUS IrpWriteFile(
	IN	PFILE_OBJECT pFileObject,
	OUT PIO_STATUS_BLOCK IoStatusBlock,
	IN	PVOID Buffer,
	IN	ULONG BufferLength,
	IN	PLARGE_INTEGER ByteOffset OPTIONAL)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_OBJECT pDevObj = NULL;
	PIRP pIRP = NULL;
	KEVENT kEvent = { 0 };
	PIO_STACK_LOCATION pIoStackLocation = NULL;

	if (NULL == pFileObject)
	{
		return STATUS_UNSUCCESSFUL;
	}
	if (NULL == pFileObject->Vpb)
	{
		return STATUS_UNSUCCESSFUL;
	}
	pDevObj = pFileObject->Vpb->DeviceObject;
	if (NULL == pDevObj)
	{
		return STATUS_UNSUCCESSFUL;
	}
	
	if (NULL == ByteOffset)
	{
		if (0 == (FO_SYNCHRONOUS_IO & pFileObject->Flags))
		{
			return STATUS_INVALID_PARAMETER;
		}
		ByteOffset = &pFileObject->CurrentByteOffset;
	}
	
	pIRP = IoAllocateIrp(pDevObj->StackSize, FALSE);
	if (NULL == pIRP)
	{
		return STATUS_UNSUCCESSFUL;
	}
	KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
	
	pIRP->MdlAddress = MmCreateMdl(NULL, Buffer, BufferLength);
	if (NULL == pIRP->MdlAddress)
	{
		IoFreeIrp(pIRP);
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	MmBuildMdlForNonPagedPool(pIRP->MdlAddress);
	pIRP->UserEvent = &kEvent;
	pIRP->UserIosb = IoStatusBlock;
	pIRP->Flags = IRP_WRITE_OPERATION;
	pIRP->RequestorMode = KernelMode;
	pIRP->Tail.Overlay.Thread = PsGetCurrentThread();
	pIRP->Tail.Overlay.OriginalFileObject = pFileObject;
	
	pIoStackLocation = IoGetNextIrpStackLocation(pIRP);
	pIoStackLocation->MajorFunction = IRP_MJ_WRITE;
	pIoStackLocation->MinorFunction = IRP_MN_NORMAL;
	pIoStackLocation->DeviceObject = pDevObj;
	pIoStackLocation->FileObject = pFileObject;
	pIoStackLocation->Parameters.Write.Length = BufferLength;
	pIoStackLocation->Parameters.Write.ByteOffset = *ByteOffset;
	
	IoSetCompletionRoutine(pIRP, CompleteRoutine, NULL, TRUE, TRUE, TRUE);
	
	status = IoCallDriver(pDevObj, pIRP);
	
	if (STATUS_PENDING == status)
	{
		KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
	}
	
	return IoStatusBlock->Status;
}

Maybe I just want to know that how to make write file by build IRP like writefile funtion on Ring3 that it can change file size autoly.

Unless this is the network (seems unlikely)this is at least the wrong FO (because otherwise it would have a vpb) and hence probably the wrong DO

thanks! Rod. this funtion had return STATUS_SUCCUSS,and I can make sure the FO and DO right. I am get the FO by code like:


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;

Technically, the file object is in an invalid state for a non paging write. It doesn't have FO_HANDLE_CREATED flag, this might indicate to a file system it needs to process only paging IO.

I suggest to use general routines to create a file object and a handle, like IoCreateFile.

BTW, paging IO cannot change the file size.

ok,thanks Slava.I want to avoid re-entry.

To avoid reentry use IoCreateFileSpecifyDeviceObjectHint .

1 Like

Thank you once again sincerely for your help! Slava.But it like hang after used a handle made by IoCreateFileSpecifyDeviceObjectHint to operate file. code:

InitializeObjectAttributes(&objAttr,
		&ustrSnapShotName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL);
	status = IoCreateFileSpecifyDeviceObjectHint(
		&htmp,
		GENERIC_READ | GENERIC_WRITE,
		&objAttr,
		&ioBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		0,
		FILE_OPEN_IF,
		FILE_SYNCHRONOUS_IO_NONALERT | FILE_NO_INTERMEDIATE_BUFFERING,
		NULL,
		0,
		CreateFileTypeNone,
		NULL,
		0,
		IoGetDeviceAttachmentBaseRef(g_pTargeDevExt->pFltDevObj)
	);
	if (!NT_SUCCESS(status))
	{
		KeBugCheck(status);
	}	
	ObDereferenceObject(g_pTargeDevExt->pFltDevObj);
  • If file write hangs, take the thread call stack in WinDbg and find the reason. It is not generally related to IoCreateFileSpecifyDeviceObjectHint, it just returns a file object and a handle. There is nothing special about this handle and file object, except a hint for target device object.
  • FILE_NO_INTERMEDIATE_BUFFERING requires offset and buffer aligned on a file system block / sector size

Ok,I will to do by your tips,thanks!Good a Day!