|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
FileInfo.c
Abstract:
This module implements the File Info routines for NPFS called by the dispatch driver. There are two entry points NpFsdQueryInformation and NpFsdSetInformation.
Author:
Gary Kimura [GaryKi] 21-Aug-1990
Revision History:
--*/
#include "NpProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (NPFS_BUG_CHECK_FILEINFO)
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_FILEINFO)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NpCommonQueryInformation)
#pragma alloc_text(PAGE, NpCommonSetInformation)
#pragma alloc_text(PAGE, NpFsdQueryInformation)
#pragma alloc_text(PAGE, NpFsdSetInformation)
#pragma alloc_text(PAGE, NpQueryBasicInfo)
#pragma alloc_text(PAGE, NpQueryEaInfo)
#pragma alloc_text(PAGE, NpQueryInternalInfo)
#pragma alloc_text(PAGE, NpQueryNameInfo)
#pragma alloc_text(PAGE, NpQueryPipeInfo)
#pragma alloc_text(PAGE, NpQueryPipeLocalInfo)
#pragma alloc_text(PAGE, NpQueryPositionInfo)
#pragma alloc_text(PAGE, NpQueryStandardInfo)
#pragma alloc_text(PAGE, NpSetBasicInfo)
#pragma alloc_text(PAGE, NpSetPipeInfo)
#endif
NTSTATUS NpFsdQueryInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtQueryInformationFile 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, "NpFsdQueryInformation\n", 0);
//
// Call the common Query Information routine.
//
FsRtlEnterFileSystem();
NpAcquireSharedVcb();
Status = NpCommonQueryInformation( NpfsDeviceObject, Irp );
NpReleaseVcb();
FsRtlExitFileSystem();
if (Status != STATUS_PENDING) { NpCompleteRequest (Irp, Status); } //
// And return to our caller
//
DebugTrace(-1, Dbg, "NpFsdQueryInformation -> %08lx\n", Status );
return Status; }
NTSTATUS NpFsdSetInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtSetInformationFile 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; LIST_ENTRY DeferredList;
PAGED_CODE();
DebugTrace(+1, Dbg, "NpFsdSetInformation\n", 0);
//
// Call the common Set Information routine.
//
InitializeListHead (&DeferredList);
FsRtlEnterFileSystem ();
NpAcquireExclusiveVcb ();
Status = NpCommonSetInformation (NpfsDeviceObject, Irp, &DeferredList);
NpReleaseVcb ();
//
// Complete the deferred IRPs now we have released the locks
//
NpCompleteDeferredIrps (&DeferredList);
FsRtlExitFileSystem ();
if (Status != STATUS_PENDING) { NpCompleteRequest (Irp, Status); } //
// And return to our caller
//
DebugTrace(-1, Dbg, "NpFsdSetInformation -> %08lx\n", Status ); return Status; }
//
// Internal support routine
//
NTSTATUS NpCommonQueryInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for creating/opening a file.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{ PIO_STACK_LOCATION IrpSp; NTSTATUS Status;
ULONG Length; FILE_INFORMATION_CLASS FileInformationClass; PVOID Buffer;
NODE_TYPE_CODE NodeTypeCode; PFCB Fcb; PCCB Ccb; NAMED_PIPE_END NamedPipeEnd;
PFILE_ALL_INFORMATION AllInfo;
PAGED_CODE();
//
// Get the current stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "NpCommonQueryInformation...\n", 0); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryFile.Length); DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryFile.FileInformationClass); DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
//
// Get the ccb and figure out who we are, and make sure we're not
// disconnected.
//
if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb, &NamedPipeEnd )) == NTC_UNDEFINED) {
DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0);
Status = STATUS_PIPE_DISCONNECTED;
DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status ); return Status; }
//
// Reference our input parameter to make things easier
//
Length = IrpSp->Parameters.QueryFile.Length; FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Case on the type of the context, We can only query information
// on an Fcb, Dcb, or Root Dcb. If we are not passed on of these
// we immediately tell the caller that there is an invalid parameter.
//
if (NodeTypeCode != NPFS_NTC_CCB && (NodeTypeCode != NPFS_NTC_ROOT_DCB || FileInformationClass != FileNameInformation)) {
DebugTrace(0, Dbg, "Node type code is not ccb\n", 0);
DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; }
//
// Based on the information class we'll do different actions. Each
// of the procedure that we're calling fill up as much of the
// buffer as possible and return the remaining length, and status
// This is done so that we can use them to build up the
// FileAllInformation request. These procedures do not complete the
// Irp, instead this procedure must complete the Irp.
//
switch (FileInformationClass) {
case FileAllInformation:
//
// For the all information class we'll typecast a local
// pointer to the output buffer and then call the
// individual routines to fill in the buffer.
//
AllInfo = Buffer;
Length -= (sizeof(FILE_ACCESS_INFORMATION) + sizeof(FILE_MODE_INFORMATION) + sizeof(FILE_ALIGNMENT_INFORMATION));
//
// Only the QueryName call can return non-success
//
(VOID)NpQueryBasicInfo( Ccb, &AllInfo->BasicInformation, &Length ); (VOID)NpQueryStandardInfo( Ccb, &AllInfo->StandardInformation, &Length, NamedPipeEnd ); (VOID)NpQueryInternalInfo( Ccb, &AllInfo->InternalInformation, &Length ); (VOID)NpQueryEaInfo( Ccb, &AllInfo->EaInformation, &Length ); (VOID)NpQueryPositionInfo( Ccb, &AllInfo->PositionInformation, &Length, NamedPipeEnd );
Status = NpQueryNameInfo( Ccb, &AllInfo->NameInformation, &Length );
break;
case FileBasicInformation:
Status = NpQueryBasicInfo( Ccb, Buffer, &Length ); break;
case FileStandardInformation:
Status = NpQueryStandardInfo( Ccb, Buffer, &Length, NamedPipeEnd ); break;
case FileInternalInformation:
Status = NpQueryInternalInfo( Ccb, Buffer, &Length ); break;
case FileEaInformation:
Status = NpQueryEaInfo( Ccb, Buffer, &Length ); break;
case FilePositionInformation:
Status = NpQueryPositionInfo( Ccb, Buffer, &Length, NamedPipeEnd ); break;
case FileNameInformation:
Status = NpQueryNameInfo( Ccb, Buffer, &Length ); break;
case FilePipeInformation:
Status = NpQueryPipeInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd ); break;
case FilePipeLocalInformation:
Status = NpQueryPipeLocalInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd ); break;
default:
Status = STATUS_INVALID_PARAMETER; break; }
//
// Set the information field to the number of bytes actually filled in
// and then complete the request
//
Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status ); return Status; }
//
// Internal support routine
//
NTSTATUS NpCommonSetInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp, IN PLIST_ENTRY DeferredList )
/*++
Routine Description:
This is the common routine for creating/opening a file.
Arguments:
NpfsDeviceObject - Device object for npfs
Irp - Supplies the Irp to process
DeferredList - List or IRPs to complete after we drop locks
Return Value:
NTSTATUS - the return status for the operation
--*/
{ PIO_STACK_LOCATION IrpSp; NTSTATUS Status;
ULONG Length; FILE_INFORMATION_CLASS FileInformationClass; PVOID Buffer;
NODE_TYPE_CODE NodeTypeCode; PFCB Fcb; PCCB Ccb; NAMED_PIPE_END NamedPipeEnd;
PAGED_CODE();
//
// Get the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "NpCommonSetInformation...\n", 0); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.SetFile.Length); DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass); DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
//
// Get the ccb and figure out who we are, and make sure we're not
// disconnected.
//
if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb, &NamedPipeEnd )) == NTC_UNDEFINED) {
DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0);
Status = STATUS_PIPE_DISCONNECTED;
DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status ); return Status; }
//
// Case on the type of the context, We can only query information
// on an Fcb, Dcb, or Root Dcb. If we are not passed on of these
// we immediately tell the caller that there is an invalid parameter.
//
if (NodeTypeCode != NPFS_NTC_CCB) {
DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; }
//
// Reference our input parameter to make things easier
//
Length = IrpSp->Parameters.SetFile.Length; FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Based on the information class we'll do differnt actions. Each
// procedure that we're calling will complete the request.
//
switch (FileInformationClass) {
case FileBasicInformation:
Status = NpSetBasicInfo( Ccb, Buffer ); break;
case FilePipeInformation:
Status = NpSetPipeInfo( Fcb, Ccb, Buffer, NamedPipeEnd, DeferredList ); break;
default:
Status = STATUS_INVALID_PARAMETER; break; }
DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status); return Status; }
//
// Internal support routine
//
NTSTATUS NpQueryBasicInfo ( IN PCCB Ccb, IN PFILE_BASIC_INFORMATION Buffer, IN OUT PULONG Length )
/*++
Routine Description:
This routine performs the query basic information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
Return Value:
NTSTATUS - The result of this query
--*/
{ UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "NpQueryBasicInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof( FILE_BASIC_INFORMATION ); RtlZeroMemory( Buffer, sizeof(FILE_BASIC_INFORMATION) );
//
// Set the various fields in the record
//
//**** need to add the time fields to the fcb/ccb
//
Buffer->CreationTime.LowPart = 0; Buffer->CreationTime.HighPart = 0; Buffer->LastAccessTime.LowPart = 0; Buffer->LastAccessTime.HighPart = 0; Buffer->LastWriteTime.LowPart = 0; Buffer->LastWriteTime.HighPart = 0; Buffer->ChangeTime.LowPart = 0; Buffer->ChangeTime.HighPart = 0;
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
//
// and return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryStandardInfo ( IN PCCB Ccb, IN PFILE_STANDARD_INFORMATION Buffer, IN OUT PULONG Length, IN NAMED_PIPE_END NamedPipeEnd )
/*++
Routine Description:
This routine performs the query standard information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
Return Value:
NTSTATUS - The result of this query
--*/
{ PDATA_QUEUE Inbound; PDATA_QUEUE Outbound; PDATA_QUEUE Queue;
PAGED_CODE();
DebugTrace(0, Dbg, "NpQueryStandardInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof( FILE_STANDARD_INFORMATION ); RtlZeroMemory( Buffer, sizeof(FILE_STANDARD_INFORMATION) );
//
// Set the various fields in the record
//
Inbound = &Ccb->DataQueue[ FILE_PIPE_INBOUND ]; Outbound = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
if (NamedPipeEnd == FILE_PIPE_CLIENT_END) { Queue = Outbound; } else { Queue = Inbound; } //
// The allocation size is the amount of quota we've charged this pipe
// instance
//
Buffer->AllocationSize.QuadPart = Inbound->Quota + Outbound->Quota;
//
// The Eof is the number of writen bytes ready to be read from the queue
//
if (NpIsDataQueueWriters( Queue )) { Buffer->EndOfFile.QuadPart = Queue->BytesInQueue - Queue->NextByteOffset; }
Buffer->NumberOfLinks = 1; Buffer->DeletePending = TRUE; Buffer->Directory = FALSE;
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryInternalInfo ( IN PCCB Ccb, IN PFILE_INTERNAL_INFORMATION Buffer, IN OUT PULONG Length )
/*++
Routine Description:
This routine performs the query internal information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
Return Value:
NTSTATUS - The result of this query
--*/
{ PAGED_CODE();
DebugTrace(0, Dbg, "NpQueryInternalInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof(FILE_INTERNAL_INFORMATION); RtlZeroMemory(Buffer, sizeof(FILE_INTERNAL_INFORMATION));
//
// Set the internal index number to be the fnode lbn;
//
Buffer->IndexNumber.QuadPart = (ULONG_PTR)Ccb;
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryEaInfo ( IN PCCB Ccb, IN PFILE_EA_INFORMATION Buffer, IN OUT PULONG Length )
/*++
Routine Description:
This routine performs the query Ea information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
Return Value:
NTSTATUS - The result of this query
--*/
{ UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "NpQueryEaInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof(FILE_EA_INFORMATION); RtlZeroMemory(Buffer, sizeof(FILE_EA_INFORMATION));
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryNameInfo ( IN PCCB Ccb, IN PFILE_NAME_INFORMATION Buffer, IN OUT PULONG Length )
/*++
Routine Description:
This routine performs the query name information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
Return Value:
NTSTATUS - The result of this query
--*/
{ ULONG bytesToCopy; ULONG fileNameSize; PFCB Fcb;
NTSTATUS status;
PAGED_CODE();
DebugTrace(0, Dbg, "NpQueryNameInfo...\n", 0);
//
// See if the buffer is large enough, and decide how many bytes to copy.
//
*Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName[0] );
if (Ccb->NodeTypeCode == NPFS_NTC_ROOT_DCB_CCB) { Fcb = NpVcb->RootDcb; } else { Fcb = Ccb->Fcb; } fileNameSize = Fcb->FullFileName.Length;
if ( *Length >= fileNameSize ) {
status = STATUS_SUCCESS;
bytesToCopy = fileNameSize;
} else {
status = STATUS_BUFFER_OVERFLOW;
bytesToCopy = *Length; }
//
// Copy over the file name and its length.
//
RtlCopyMemory( Buffer->FileName, Fcb->FullFileName.Buffer, bytesToCopy);
Buffer->FileNameLength = bytesToCopy;
*Length -= bytesToCopy;
return status; }
//
// Internal support routine
//
NTSTATUS NpQueryPositionInfo ( IN PCCB Ccb, IN PFILE_POSITION_INFORMATION Buffer, IN OUT PULONG Length, IN NAMED_PIPE_END NamedPipeEnd )
/*++
Routine Description:
This routine performs the query position information operation.
Arguments:
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
NamedPipeEnd - Indicates if the server or client is calling
Return Value:
NTSTATUS - The result of this query
--*/
{ PDATA_QUEUE Queue;
PAGED_CODE();
DebugTrace(0, Dbg, "PbQueryPositionInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof(FILE_POSITION_INFORMATION); RtlZeroMemory(Buffer, sizeof(FILE_POSITION_INFORMATION));
//
// The current byte offset is the number of bytes available in the
// read end of the caller's buffer. The client read from the outbound
// end and the server reads from the inbound end.
//
if (NamedPipeEnd == FILE_PIPE_CLIENT_END) { Queue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ]; } else { Queue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
} if (NpIsDataQueueWriters( Queue )) { Buffer->CurrentByteOffset.QuadPart = Queue->BytesInQueue - Queue->NextByteOffset; }
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryPipeInfo ( IN PFCB Fcb, IN PCCB Ccb, IN PFILE_PIPE_INFORMATION Buffer, IN OUT PULONG Length, IN NAMED_PIPE_END NamedPipeEnd )
/*++
Routine Description:
This routine performs the query pipe information operation.
Arguments:
Fcb - Supplies the Fcb of the named pipe being queried
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
NamedPipeEnd - Indicates if the server or client is calling
Return Value:
NTSTATUS - The result of this query
--*/
{ UNREFERENCED_PARAMETER( Fcb ); UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "PbQueryPipeInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof(FILE_PIPE_INFORMATION); RtlZeroMemory(Buffer, sizeof(FILE_PIPE_INFORMATION));
//
// Set the fields in the record
//
Buffer->ReadMode = Ccb->ReadCompletionMode[ NamedPipeEnd ].ReadMode; Buffer->CompletionMode = Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode;
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpQueryPipeLocalInfo ( IN PFCB Fcb, IN PCCB Ccb, IN PFILE_PIPE_LOCAL_INFORMATION Buffer, IN OUT PULONG Length, IN NAMED_PIPE_END NamedPipeEnd )
/*++
Routine Description:
This routine performs the query pipe information operation.
Arguments:
Fcb - Supplies the Fcb of the named pipe being queried
Ccb - Supplies the Ccb of the named pipe being queried
Buffer - Supplies a pointer to the buffer where the information is to be returned
Length - Supplies the length of the buffer in bytes. This variable upon return will receive the remaining bytes free in the buffer.
NamedPipeEnd - Indicates if the server or client is calling
Return Value:
NTSTATUS - The result of this query
--*/
{ PDATA_QUEUE Inbound; PDATA_QUEUE Outbound;
UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "PbQueryPipeLocalInfo...\n", 0);
//
// Update the length field, and zero out the buffer
//
*Length -= sizeof(FILE_PIPE_LOCAL_INFORMATION); RtlZeroMemory(Buffer, sizeof(FILE_PIPE_LOCAL_INFORMATION));
Inbound = &Ccb->DataQueue[ FILE_PIPE_INBOUND ]; Outbound = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
//
// Set the fields in the record
//
Buffer->NamedPipeType = Fcb->Specific.Fcb.NamedPipeType; Buffer->NamedPipeConfiguration = Fcb->Specific.Fcb.NamedPipeConfiguration; Buffer->MaximumInstances = Fcb->Specific.Fcb.MaximumInstances; Buffer->CurrentInstances = Fcb->OpenCount; Buffer->InboundQuota = Inbound->Quota; Buffer->OutboundQuota = Outbound->Quota; Buffer->NamedPipeState = Ccb->NamedPipeState; Buffer->NamedPipeEnd = NamedPipeEnd;
//
// The read data available and write quota available depend on which
// end of the pipe is doing the query. The client reads from the outbound
// queue, and writes to the inbound queue.
//
if (NamedPipeEnd == FILE_PIPE_CLIENT_END) {
if (NpIsDataQueueWriters( Outbound )) {
Buffer->ReadDataAvailable = Outbound->BytesInQueue - Outbound->NextByteOffset; }
Buffer->WriteQuotaAvailable = Inbound->Quota - Inbound->QuotaUsed;
} else {
if (NpIsDataQueueWriters( Inbound )) {
Buffer->ReadDataAvailable = Inbound->BytesInQueue - Inbound->NextByteOffset; }
Buffer->WriteQuotaAvailable = Outbound->Quota - Outbound->QuotaUsed; }
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpSetBasicInfo ( IN PCCB Ccb, IN PFILE_BASIC_INFORMATION Buffer )
/*++
Routine Description:
This routine sets the basic information for a named pipe.
Arguments:
Ccb - Supplies the ccb for the named pipe being modified
Buffer - Supplies the buffer containing the data being set
Return Value:
NTSTATUS - Returns our completion status
--*/
{ UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "NpSetBasicInfo...\n", 0);
if (((PLARGE_INTEGER)&Buffer->CreationTime)->QuadPart != 0) {
//
// Modify the creation time
//
//**** need to add time fields
}
if (((PLARGE_INTEGER)&Buffer->LastAccessTime)->QuadPart != 0) {
//
// Modify the last access time
//
//**** need to add time fields
}
if (((PLARGE_INTEGER)&Buffer->LastWriteTime)->QuadPart != 0) {
//
// Modify the last write time
//
//**** need to add time fields
}
if (((PLARGE_INTEGER)&Buffer->ChangeTime)->QuadPart != 0) {
//
// Modify the change time
//
//**** need to add time fields
}
//
// And return to our caller
//
return STATUS_SUCCESS; }
//
// Internal support routine
//
NTSTATUS NpSetPipeInfo ( IN PFCB Fcb, IN PCCB Ccb, IN PFILE_PIPE_INFORMATION Buffer, IN NAMED_PIPE_END NamedPipeEnd, IN PLIST_ENTRY DeferredList )
/*++
Routine Description:
This routine sets the pipe information for a named pipe.
Arguments:
Fcb - Supplies the Fcb for the named pipe being modified
Ccb - Supplies the ccb for the named pipe being modified
Buffer - Supplies the buffer containing the data being set
NamedPipeEnd - Supplies the server/client end doing the operation
DeferredList - List of IRPs to complete once we release locks
Return Value:
NTSTATUS - Returns our completion status
--*/
{ PDATA_QUEUE ReadQueue; PDATA_QUEUE WriteQueue;
UNREFERENCED_PARAMETER( Ccb );
PAGED_CODE();
DebugTrace(0, Dbg, "NpSetPipeInfo...\n", 0);
//
// If the caller requests message mode reads but the pipe is
// byte stream then its an invalid parameter
//
if ((Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE) && (Fcb->Specific.Fcb.NamedPipeType == FILE_PIPE_BYTE_STREAM_MODE)) {
return STATUS_INVALID_PARAMETER; }
//
// Get a reference to our read queue
//
switch (NamedPipeEnd) {
case FILE_PIPE_SERVER_END:
ReadQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ]; WriteQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
break;
case FILE_PIPE_CLIENT_END:
ReadQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ]; WriteQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
break;
default:
NpBugCheck( NamedPipeEnd, 0, 0 ); }
//
// If the completion mode is complete operations and the current mode
// is queue operations and there and the data queues are not empty
// then its pipe busy
//
if ((Buffer->CompletionMode == FILE_PIPE_COMPLETE_OPERATION)
&&
(Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode == FILE_PIPE_QUEUE_OPERATION)
&&
((NpIsDataQueueReaders(ReadQueue)) || (NpIsDataQueueWriters(WriteQueue)))) {
return STATUS_PIPE_BUSY; }
//
// Everything is fine so update the pipe
//
Ccb->ReadCompletionMode[ NamedPipeEnd ].ReadMode = (UCHAR) Buffer->ReadMode; Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode = (UCHAR) Buffer->CompletionMode;
//
// Check for notify
//
NpCheckForNotify( Fcb->ParentDcb, FALSE, DeferredList );
//
// And return to our caller
//
return STATUS_SUCCESS; }
|