Hi,
I would like to build an IRP to flush all the cache in C drive to files.
Currently I am able to use Win 32 API to flush the cache. However, I would
like to flush it in kernel mode, as soon as IRP_MJ_CLEANUP is completed.
This is to force IO Manager to issue IRP_MJ_CLOSE for that particular file.
I tried to build an IRP but I still don’t get the IRP_MJ_CLOSE request after
the IRP is sent down to the lower file system.
Please suggest how to solve this problem. Thanks!
Regards,
Sin Lam
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
//This routine is called to flush the cache in C drive as soon as
IRP_MJ_CLEANUP
//for a specific file is completed.
NTSTATUS ForceFlushBuffer() {
PIRP Irp;
NTSTATUS Status = STATUS_SUCCESS;
KEVENT Event;
IO_STATUS_BLOCK Iosb;
HANDLE ntFileHandle;
OBJECT_ATTRIBUTES objectAttributes;
PFILE_OBJECT pFO;
PDEVICE_OBJECT pDO;
UNICODE_STRING fileNameUnicodeString;
WCHAR filename = L"\DosDevices\C:";
PIO_STACK_LOCATION ioStackLocation;
RtlInitUnicodeString(&fileNameUnicodeString, filename);
InitializeObjectAttributes( &objectAttributes, &fileNameUnicodeString,
OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = ZwCreateFile( &ntFileHandle, SYNCHRONIZE,
&objectAttributes, &Iosb, NULL, 0,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING,
NULL, 0 );
if ( !NT_SUCCESS( Status ) ) {
DbgPrint((“### ForceFlushBuffer: ZwCreateFile failed with status =
%x\n”, Status));
return STATUS_UNSUCCESSFUL;
}
Status = ObReferenceObjectByHandle( ntFileHandle, FILE_READ_DATA,
NULL, KernelMode, &pFO, NULL );
if ( !NT_SUCCESS( Status )) {
DbgPrint((“### ForceFlushBuffer: ObReferenceObjectByHandle failed
with status = %x\n”, Status));
ZwClose( ntFileHandle );
return STATUS_UNSUCCESSFUL;
}
pDO = IoGetRelatedDeviceObject( pFO );
if ( !pDO ) {
DbgPrint((“### ForceFlushBuffer: IoGetRelatedDeviceObject failed
with status = %x\n”, Status));
ObDereferenceObject( pFO );
ZwClose( ntFileHandle );
return STATUS_UNSUCCESSFUL;
}
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, //Major
function
pDO, //lower file system
NULL, //out buffer
0, //Length
0, //StartingOffset
&Event, // Event object
&Iosb); // status block to be set
if (!Irp) {
DbgPrint((“### IoBuildSynchronousFsdRequest failed!\n”));
ObDereferenceObject(pFO);
ZwClose( ntFileHandle );
return STATUS_UNSUCCESSFUL;
}
ioStackLocation = IoGetNextIrpStackLocation(Irp);
ioStackLocation->DeviceObject = pDO;
ioStackLocation->FileObject = pFO;
Status = IoCallDriver(pDO, Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
Status = Iosb.Status;
}
ObDereferenceObject(pFO);
ZwClose( ntFileHandle );
if (Iosb.Status != STATUS_SUCCESS) {
DbgPrint((“### ForceFlushBuffer failed!\n”));
return STATUS_ACCESS_DENIED;
}
return STATUS_SUCCESS;
}