227 lines
4.5 KiB
C
227 lines
4.5 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
FlushBuf.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the File Flush Buffers routine for NPFS called by
|
|||
|
the dispatch driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 21-Aug-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "NpProcs.h"
|
|||
|
|
|||
|
//
|
|||
|
// The debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_FLUSH_BUFFERS)
|
|||
|
|
|||
|
//
|
|||
|
// local procedure prototypes
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpCommonFlushBuffers (
|
|||
|
IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, NpCommonFlushBuffers)
|
|||
|
#pragma alloc_text(PAGE, NpFsdFlushBuffers)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpFsdFlushBuffers (
|
|||
|
IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FSD part of the NtFlushBuffersFile API calls.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NpfsDeviceObject - Supplies the device object to use.
|
|||
|
|
|||
|
Irp - Supplies the Irp being processed
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - The Fsd status for the Irp
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpFsdFlushBuffers\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Call the common Flush routine.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
NpAcquireSharedVcb();
|
|||
|
|
|||
|
Status = NpCommonFlushBuffers( NpfsDeviceObject, Irp );
|
|||
|
|
|||
|
NpReleaseVcb();
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
if (Status != STATUS_PENDING) {
|
|||
|
NpCompleteRequest( Irp, Status );
|
|||
|
}
|
|||
|
//
|
|||
|
// And return to our caller
|
|||
|
//
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpFsdFlushBuffers -> %08lx\n", Status );
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Internal support routine
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NpCommonFlushBuffers (
|
|||
|
IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for Flushing buffers for a file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Supplies the Irp to process
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - the return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PIO_STACK_LOCATION IrpSp;
|
|||
|
|
|||
|
PCCB Ccb;
|
|||
|
NAMED_PIPE_END NamedPipeEnd;
|
|||
|
|
|||
|
PDATA_QUEUE WriteQueue;
|
|||
|
|
|||
|
//
|
|||
|
// Get the current stack location
|
|||
|
//
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "NpCommonFlushBuffers\n", 0);
|
|||
|
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp);
|
|||
|
DebugTrace( 0, Dbg, "FileObject = %08lx\n", IrpSp->FileObject);
|
|||
|
|
|||
|
//
|
|||
|
// Decode the file object to figure out who we are. If the result
|
|||
|
// is not a ccb then the pipe has been disconnected. We don't need the
|
|||
|
// Fcb back from the call
|
|||
|
//
|
|||
|
|
|||
|
if (NpDecodeFileObject( IrpSp->FileObject,
|
|||
|
NULL,
|
|||
|
&Ccb,
|
|||
|
&NamedPipeEnd ) != NPFS_NTC_CCB) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0);
|
|||
|
|
|||
|
Status = STATUS_PIPE_DISCONNECTED;
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpCommonFlushBuffers -> %08lx\n", Status );
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NpAcquireExclusiveCcb(Ccb);
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// Figure out the data queue that the flush buffer is
|
|||
|
// targetted at. It is the queue that we do writes into
|
|||
|
//
|
|||
|
|
|||
|
if (NamedPipeEnd == FILE_PIPE_SERVER_END) {
|
|||
|
|
|||
|
WriteQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
WriteQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now from the write queue check if contains write entries. If
|
|||
|
// it does not contain write entries then we immediately complete
|
|||
|
// this irp with success because there isn't anything to flush
|
|||
|
//
|
|||
|
|
|||
|
if (!NpIsDataQueueWriters( WriteQueue )) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Pipe does not contain write entries\n", 0);
|
|||
|
|
|||
|
try_return(Status = STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Otherwise the queue is full of writes so we simply
|
|||
|
// enqueue this irp to the back to the queue and set our
|
|||
|
// return status to pending, also mark the irp pending
|
|||
|
//
|
|||
|
|
|||
|
Status = NpAddDataQueueEntry( NamedPipeEnd,
|
|||
|
Ccb,
|
|||
|
WriteQueue,
|
|||
|
WriteEntries,
|
|||
|
Flush,
|
|||
|
0,
|
|||
|
Irp,
|
|||
|
NULL,
|
|||
|
0 );
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
NpReleaseCcb(Ccb);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "NpCommonFlushBuffers -> %08lx\n", Status);
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|