1130 lines
24 KiB
C
1130 lines
24 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
fileinfo.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the get / set file information routines for
|
|||
|
MSFS called by the dispatch driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Manny Weiser (mannyw) 31-Jan-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "mailslot.h"
|
|||
|
|
|||
|
//
|
|||
|
// The debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_FILEINFO)
|
|||
|
|
|||
|
//
|
|||
|
// local procedure prototypes
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsCommonQueryInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsCommonSetInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryBasicInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_BASIC_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryStandardInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_STANDARD_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryInternalInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_INTERNAL_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryEaInfo (
|
|||
|
IN PFILE_EA_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsQueryNameInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_NAME_INFORMATION Buffer,
|
|||
|
IN OUT PULONG Length
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryPositionInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_POSITION_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryMailslotInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_MAILSLOT_QUERY_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsSetBasicInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_BASIC_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsSetMailslotInfo (
|
|||
|
IN PIRP Irp,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_MAILSLOT_SET_INFORMATION Buffer
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text( PAGE, MsCommonQueryInformation )
|
|||
|
#pragma alloc_text( PAGE, MsCommonSetInformation )
|
|||
|
#pragma alloc_text( PAGE, MsFsdQueryInformation )
|
|||
|
#pragma alloc_text( PAGE, MsFsdSetInformation )
|
|||
|
#pragma alloc_text( PAGE, MsQueryBasicInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryEaInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryInternalInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryMailslotInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryNameInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryPositionInfo )
|
|||
|
#pragma alloc_text( PAGE, MsQueryStandardInfo )
|
|||
|
#pragma alloc_text( PAGE, MsSetBasicInfo )
|
|||
|
#pragma alloc_text( PAGE, MsSetMailslotInfo )
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsFsdQueryInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FSD part of the NtQueryInformationFile API
|
|||
|
calls.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MsfsDeviceObject - Supplies a pointer to the device object to use.
|
|||
|
|
|||
|
Irp - Supplies a pointer to the Irp to process.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - The Fsd status for the Irp
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(+1, Dbg, "MsFsdQueryInformation\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Call the common query information routine.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
status = MsCommonQueryInformation( MsfsDeviceObject, Irp );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
//
|
|||
|
// Return to the caller.
|
|||
|
//
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsFsdQueryInformation -> %08lx\n", status );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsFsdSetInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the FSD part of the NtSetInformationFile API
|
|||
|
calls.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MsfsDeviceObject - 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, "MsFsdSetInformation\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Call the common Set Information routine.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
status = MsCommonSetInformation( MsfsDeviceObject, Irp );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
//
|
|||
|
// Return to the caller.
|
|||
|
//
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsFsdSetInformation -> %08lx\n", status );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsCommonQueryInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for querying information on a file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MsfsDeviceObject - The device object to use.
|
|||
|
|
|||
|
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;
|
|||
|
|
|||
|
PVOID fsContext, fsContext2;
|
|||
|
|
|||
|
PFILE_ALL_INFORMATION AllInfo;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Get the current stack location.
|
|||
|
//
|
|||
|
|
|||
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "MsCommonQueryInformation...\n", 0);
|
|||
|
DebugTrace( 0, Dbg, " Irp = %08lx\n", (ULONG)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", (ULONG)Irp->AssociatedIrp.SystemBuffer);
|
|||
|
|
|||
|
//
|
|||
|
// Find out who are.
|
|||
|
//
|
|||
|
|
|||
|
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
|
|||
|
&fsContext,
|
|||
|
&fsContext2 )) == NTC_UNDEFINED) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Mailslot is disconnected from us\n", 0);
|
|||
|
|
|||
|
MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
|
|||
|
status = STATUS_FILE_FORCED_CLOSED;
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonQueryInformation -> %08lx\n", status );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Decide how to handle this request. A user can query information
|
|||
|
// on a DCB, ROOT_DCB, FCB, or CCB only.
|
|||
|
//
|
|||
|
|
|||
|
switch (nodeTypeCode) {
|
|||
|
|
|||
|
case MSFS_NTC_FCB: // This is a server side handle to a mailslot file
|
|||
|
case MSFS_NTC_ROOT_DCB: // This is the MSFS root directory
|
|||
|
|
|||
|
fcb = (PFCB)fsContext;
|
|||
|
break;
|
|||
|
|
|||
|
default: // This is an illegal file object to query
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "Node type code is not incorrect\n", 0);
|
|||
|
|
|||
|
MsDereferenceNode( (PNODE_HEADER)fsContext );
|
|||
|
|
|||
|
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0);
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make local copies of the input parameters.
|
|||
|
//
|
|||
|
|
|||
|
length = irpSp->Parameters.QueryFile.Length;
|
|||
|
fileInformationClass = irpSp->Parameters.QueryFile.FileInformationClass;
|
|||
|
buffer = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// Now acquire shared access to the FCB
|
|||
|
//
|
|||
|
|
|||
|
MsAcquireSharedFcb( fcb );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// 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.
|
|||
|
//
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
|
|||
|
switch (fileInformationClass) {
|
|||
|
|
|||
|
case FileAllInformation:
|
|||
|
|
|||
|
AllInfo = buffer;
|
|||
|
|
|||
|
MsQueryBasicInfo( fcb, &AllInfo->BasicInformation );
|
|||
|
MsQueryStandardInfo( fcb, &AllInfo->StandardInformation );
|
|||
|
MsQueryInternalInfo( fcb, &AllInfo->InternalInformation );
|
|||
|
MsQueryEaInfo( &AllInfo->EaInformation );
|
|||
|
MsQueryPositionInfo( fcb, &AllInfo->PositionInformation );
|
|||
|
|
|||
|
length -= FIELD_OFFSET( FILE_ALL_INFORMATION, NameInformation );
|
|||
|
|
|||
|
status = MsQueryNameInfo( fcb, &AllInfo->NameInformation, &length );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case FileBasicInformation:
|
|||
|
|
|||
|
MsQueryBasicInfo( fcb, buffer );
|
|||
|
|
|||
|
length -= sizeof( FILE_BASIC_INFORMATION );
|
|||
|
break;
|
|||
|
|
|||
|
case FileStandardInformation:
|
|||
|
|
|||
|
MsQueryStandardInfo( fcb, buffer );
|
|||
|
|
|||
|
length -= sizeof( FILE_STANDARD_INFORMATION );
|
|||
|
break;
|
|||
|
|
|||
|
case FileInternalInformation:
|
|||
|
|
|||
|
MsQueryInternalInfo( fcb, buffer );
|
|||
|
|
|||
|
length -= sizeof( FILE_INTERNAL_INFORMATION );
|
|||
|
break;
|
|||
|
|
|||
|
case FileEaInformation:
|
|||
|
|
|||
|
MsQueryEaInfo( buffer );
|
|||
|
|
|||
|
length -= sizeof( FILE_EA_INFORMATION );
|
|||
|
break;
|
|||
|
|
|||
|
case FilePositionInformation:
|
|||
|
|
|||
|
MsQueryPositionInfo( fcb, buffer );
|
|||
|
|
|||
|
length -= sizeof( FILE_POSITION_INFORMATION );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case FileNameInformation:
|
|||
|
|
|||
|
status = MsQueryNameInfo( fcb, buffer, &length );
|
|||
|
break;
|
|||
|
|
|||
|
case FileMailslotQueryInformation:
|
|||
|
|
|||
|
if( nodeTypeCode == MSFS_NTC_FCB ) {
|
|||
|
|
|||
|
MsQueryMailslotInfo( fcb, buffer );
|
|||
|
length -= sizeof( FILE_MAILSLOT_QUERY_INFORMATION );
|
|||
|
|
|||
|
} else {
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
MsReleaseFcb( fcb );
|
|||
|
MsDereferenceFcb( fcb );
|
|||
|
|
|||
|
//
|
|||
|
// 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;
|
|||
|
|
|||
|
MsCompleteRequest( Irp, status );
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonQueryInformation -> %08lx\n", status );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsCommonSetInformation (
|
|||
|
IN PMSFS_DEVICE_OBJECT MsfsDeviceObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for setting information on a mailslot 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;
|
|||
|
PVOID fsContext2;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Get the current Irp stack location.
|
|||
|
//
|
|||
|
|
|||
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
DebugTrace(+1, Dbg, "MsCommonSetInformation...\n", 0);
|
|||
|
DebugTrace( 0, Dbg, " Irp = %08lx\n", (ULONG)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", (ULONG)Irp->AssociatedIrp.SystemBuffer);
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the FCB and ensure that this is a server side
|
|||
|
// handler to a mailslot file.
|
|||
|
//
|
|||
|
|
|||
|
if ((nodeTypeCode = MsDecodeFileObject( irpSp->FileObject,
|
|||
|
(PVOID *)&fcb,
|
|||
|
&fsContext2 )) == NTC_UNDEFINED) {
|
|||
|
|
|||
|
DebugTrace(0, Dbg, "The mailslot is disconnected from us\n", 0);
|
|||
|
|
|||
|
MsCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED );
|
|||
|
status = STATUS_FILE_FORCED_CLOSED;
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonSetInformation -> %08lx\n", status );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Case on the type of the context, We can only set information
|
|||
|
// on an FCB.
|
|||
|
//
|
|||
|
|
|||
|
if (nodeTypeCode != MSFS_NTC_FCB) {
|
|||
|
|
|||
|
MsDereferenceNode( &fcb->Header );
|
|||
|
MsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0);
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make local copies of the input parameters.
|
|||
|
//
|
|||
|
|
|||
|
length = irpSp->Parameters.SetFile.Length;
|
|||
|
fileInformationClass = irpSp->Parameters.SetFile.FileInformationClass;
|
|||
|
buffer = Irp->AssociatedIrp.SystemBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// Acquire exclusive access to the FCB.
|
|||
|
//
|
|||
|
|
|||
|
MsAcquireExclusiveFcb( fcb );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// Based on the information class we'll do different actions. Each
|
|||
|
// procedure that we're calling will complete the request.
|
|||
|
//
|
|||
|
|
|||
|
switch (fileInformationClass) {
|
|||
|
|
|||
|
case FileBasicInformation:
|
|||
|
|
|||
|
status = MsSetBasicInfo( fcb, buffer );
|
|||
|
break;
|
|||
|
|
|||
|
case FileMailslotSetInformation:
|
|||
|
|
|||
|
status = MsSetMailslotInfo( Irp, fcb, buffer );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Directory information has changed. Complete any notify change
|
|||
|
// directory requests.
|
|||
|
//
|
|||
|
|
|||
|
MsCheckForNotify( fcb->ParentDcb, FALSE, STATUS_SUCCESS );
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
MsReleaseFcb( fcb );
|
|||
|
MsDereferenceFcb( fcb );
|
|||
|
//
|
|||
|
// Complete the request.
|
|||
|
//
|
|||
|
|
|||
|
MsCompleteRequest( Irp, status );
|
|||
|
|
|||
|
DebugTrace(-1, Dbg, "MsCommonSetInformation -> %08lx\n", status);
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryBasicInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_BASIC_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query basic information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies a pointer the FCB of mailslot being queried.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryBasicInfo...\n", 0);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( Buffer, sizeof(FILE_BASIC_INFORMATION) );
|
|||
|
|
|||
|
//
|
|||
|
// Set the various fields in the record. These times are not maintained for the root DCB0
|
|||
|
//
|
|||
|
|
|||
|
if( Fcb->Header.NodeTypeCode == MSFS_NTC_FCB ) {
|
|||
|
Buffer->CreationTime = Fcb->Specific.Fcb.CreationTime;
|
|||
|
Buffer->LastAccessTime = Fcb->Specific.Fcb.LastAccessTime;
|
|||
|
Buffer->LastWriteTime = Fcb->Specific.Fcb.LastModificationTime;
|
|||
|
Buffer->ChangeTime = Fcb->Specific.Fcb.LastChangeTime;
|
|||
|
}
|
|||
|
|
|||
|
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryStandardInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_STANDARD_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query standard information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the FCB of the mailslot being queried
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDATA_QUEUE dataQueue;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "MsQueryStandardInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( Buffer, sizeof(FILE_STANDARD_INFORMATION) );
|
|||
|
|
|||
|
//
|
|||
|
// The allocation size is the amount of quota we've charged the mailslot
|
|||
|
// creator.
|
|||
|
//
|
|||
|
|
|||
|
if( Fcb->Header.NodeTypeCode == MSFS_NTC_FCB ) {
|
|||
|
dataQueue = &Fcb->DataQueue;
|
|||
|
Buffer->AllocationSize.QuadPart = dataQueue->Quota;
|
|||
|
|
|||
|
//
|
|||
|
// The EOF is the number of written bytes ready to be read from the
|
|||
|
// mailslot.
|
|||
|
//
|
|||
|
|
|||
|
Buffer->EndOfFile.QuadPart = dataQueue->BytesInQueue;
|
|||
|
|
|||
|
Buffer->Directory = FALSE;
|
|||
|
} else {
|
|||
|
Buffer->Directory = TRUE;
|
|||
|
}
|
|||
|
Buffer->NumberOfLinks = 1;
|
|||
|
Buffer->DeletePending = TRUE;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryInternalInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_INTERNAL_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query internal information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the FCB of the mailslot being queried.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryInternalInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( Buffer, sizeof(FILE_INTERNAL_INFORMATION) );
|
|||
|
|
|||
|
//
|
|||
|
// Set the internal index number to be the address of the FCB.
|
|||
|
//
|
|||
|
|
|||
|
Buffer->IndexNumber.QuadPart = (ULONG_PTR)Fcb;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryEaInfo (
|
|||
|
IN PFILE_EA_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query Ea information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID - The result of this query
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryEaInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the buffer.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(Buffer, sizeof(FILE_EA_INFORMATION));
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsQueryNameInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_NAME_INFORMATION Buffer,
|
|||
|
IN PULONG Length
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query name information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the FCB of the mailslot to query.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned
|
|||
|
|
|||
|
Length - Supplies and receives the length of the buffer in bytes.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - The result of this query.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG bytesToCopy;
|
|||
|
ULONG fileNameSize;
|
|||
|
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryNameInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// See if the buffer is large enough, and decide how many bytes to copy.
|
|||
|
//
|
|||
|
|
|||
|
*Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName[0] );
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryPositionInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_POSITION_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query position information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the FCB of the mailslot being queried.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDATA_QUEUE dataQueue;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryPositionInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// The current byte offset is the number of bytes available to read
|
|||
|
// in the mailslot buffer.
|
|||
|
//
|
|||
|
|
|||
|
if( Fcb->Header.NodeTypeCode == MSFS_NTC_FCB ) {
|
|||
|
dataQueue = &Fcb->DataQueue;
|
|||
|
|
|||
|
Buffer->CurrentByteOffset.QuadPart = dataQueue->BytesInQueue;
|
|||
|
} else {
|
|||
|
Buffer->CurrentByteOffset.QuadPart = 0;
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsQueryMailslotInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_MAILSLOT_QUERY_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine performs the query mailslot information operation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the Fcb of the mailslot to query.
|
|||
|
|
|||
|
Buffer - Supplies a pointer to the buffer where the information is
|
|||
|
to be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PDATA_QUEUE dataQueue;
|
|||
|
PDATA_ENTRY dataEntry;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "QueryMailslotInfo...\n", 0);
|
|||
|
|
|||
|
//
|
|||
|
// Set the fields in the record.
|
|||
|
//
|
|||
|
|
|||
|
dataQueue = &Fcb->DataQueue;
|
|||
|
|
|||
|
Buffer->MaximumMessageSize = dataQueue->MaximumMessageSize;
|
|||
|
Buffer->MailslotQuota = dataQueue->Quota;
|
|||
|
Buffer->MessagesAvailable = dataQueue->EntriesInQueue;
|
|||
|
|
|||
|
Buffer->ReadTimeout = Fcb->Specific.Fcb.ReadTimeout;
|
|||
|
|
|||
|
if ( dataQueue->EntriesInQueue == 0 ) {
|
|||
|
Buffer->NextMessageSize = MAILSLOT_NO_MESSAGE;
|
|||
|
} else {
|
|||
|
dataEntry = CONTAINING_RECORD( dataQueue->DataEntryList.Flink,
|
|||
|
DATA_ENTRY,
|
|||
|
ListEntry );
|
|||
|
|
|||
|
Buffer->NextMessageSize = dataEntry->DataSize;
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsSetBasicInfo (
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_BASIC_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine sets the basic information for a mailslot.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Fcb - Supplies the FCB for the mailslot being modified.
|
|||
|
|
|||
|
Buffer - Supplies the buffer containing the data being set.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Returns our completion status.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "SetBasicInfo...\n", 0);
|
|||
|
|
|||
|
if (((PLARGE_INTEGER)&Buffer->CreationTime)->QuadPart != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Modify the creation time
|
|||
|
//
|
|||
|
|
|||
|
Fcb->Specific.Fcb.CreationTime = Buffer->CreationTime;
|
|||
|
}
|
|||
|
|
|||
|
if (((PLARGE_INTEGER)&Buffer->LastAccessTime)->QuadPart != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Modify the last access time
|
|||
|
//
|
|||
|
|
|||
|
Fcb->Specific.Fcb.LastAccessTime = Buffer->LastAccessTime;
|
|||
|
}
|
|||
|
|
|||
|
if (((PLARGE_INTEGER)&Buffer->LastWriteTime)->QuadPart != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Modify the last write time
|
|||
|
//
|
|||
|
|
|||
|
Fcb->Specific.Fcb.LastModificationTime = Buffer->LastWriteTime;
|
|||
|
}
|
|||
|
|
|||
|
if (((PLARGE_INTEGER)&Buffer->ChangeTime)->QuadPart != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Modify the change time
|
|||
|
//
|
|||
|
|
|||
|
Fcb->Specific.Fcb.LastChangeTime = Buffer->ChangeTime;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// And return to our caller
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MsSetMailslotInfo (
|
|||
|
IN PIRP Irp,
|
|||
|
IN PFCB Fcb,
|
|||
|
IN PFILE_MAILSLOT_SET_INFORMATION Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine sets the mailslot information for a mailslot.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Pointer to an irp that contains the requestor's mode.
|
|||
|
|
|||
|
Fcb - Supplies the FCB for the mailslot being modified.
|
|||
|
|
|||
|
Buffer - Supplies the buffer containing the data being set.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Returns our completion status.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN fileUpdated;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
DebugTrace(0, Dbg, "SetMaislotInfo...\n", 0);
|
|||
|
|
|||
|
fileUpdated = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Check whether or not the DefaultTimeout parameter was specified. If
|
|||
|
// so, then set it in the FCB.
|
|||
|
//
|
|||
|
|
|||
|
if (ARGUMENT_PRESENT( Buffer->ReadTimeout )) {
|
|||
|
|
|||
|
//
|
|||
|
// A read timeout parameter was specified. Check to see whether
|
|||
|
// the caller's mode is kernel and if not capture the parameter inside
|
|||
|
// of a try...except clause.
|
|||
|
//
|
|||
|
|
|||
|
if (Irp->RequestorMode != KernelMode) {
|
|||
|
try {
|
|||
|
ProbeForRead( Buffer->ReadTimeout,
|
|||
|
sizeof( LARGE_INTEGER ),
|
|||
|
sizeof( ULONG ) );
|
|||
|
|
|||
|
Fcb->Specific.Fcb.ReadTimeout = *(Buffer->ReadTimeout);
|
|||
|
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
|
|||
|
//
|
|||
|
// Something went awry attempting to access the parameter.
|
|||
|
// Get the reason for the error and return it as the status
|
|||
|
// value from this service.
|
|||
|
//
|
|||
|
|
|||
|
return GetExceptionCode();
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// The caller's mode was kernel so simply store the parameter.
|
|||
|
//
|
|||
|
|
|||
|
Fcb->Specific.Fcb.ReadTimeout = *(Buffer->ReadTimeout);
|
|||
|
}
|
|||
|
|
|||
|
fileUpdated = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update the last change time, if necessary
|
|||
|
//
|
|||
|
|
|||
|
if ( fileUpdated ) {
|
|||
|
KeQuerySystemTime( &Fcb->Specific.Fcb.LastChangeTime);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// And return to our caller
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|