mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1304 lines
28 KiB
1304 lines
28 KiB
/*++
|
|
|
|
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;
|
|
}
|