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.
561 lines
16 KiB
561 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 1989 - 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fileinfo.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the mini redirector call down routines pertaining to retrieval/
|
|
update of file/directory/volume information.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#pragma warning(error:4101) // Unreferenced local variable
|
|
|
|
//
|
|
// The local debug trace level
|
|
//
|
|
|
|
#define Dbg (DEBUG_TRACE_FILEINFO)
|
|
|
|
NTSTATUS
|
|
NulMRxQueryDirectory(
|
|
IN OUT PRX_CONTEXT RxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a directory query. Only the NT-->NT path is implemented.
|
|
|
|
Arguments:
|
|
|
|
RxContext - the RDBSS context
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
FILE_INFORMATION_CLASS FileInformationClass;
|
|
PVOID Buffer;
|
|
PULONG pLengthRemaining;
|
|
ULONG CopySize;
|
|
|
|
FileInformationClass = RxContext->Info.FileInformationClass;
|
|
Buffer = RxContext->Info.Buffer;
|
|
pLengthRemaining = &RxContext->Info.LengthRemaining;
|
|
|
|
switch (FileInformationClass)
|
|
{
|
|
case FileDirectoryInformation:
|
|
{
|
|
PFILE_DIRECTORY_INFORMATION pDirInfo = (PFILE_DIRECTORY_INFORMATION) Buffer;
|
|
CopySize = sizeof( FILE_DIRECTORY_INFORMATION );
|
|
if ( *pLengthRemaining >= CopySize )
|
|
{
|
|
RtlZeroMemory( pDirInfo, CopySize );
|
|
pDirInfo->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
pDirInfo->FileNameLength = sizeof( WCHAR );
|
|
pDirInfo->FileName[0] = L'.';
|
|
*pLengthRemaining -= CopySize;
|
|
Status = RxContext->QueryDirectory.InitialQuery ?
|
|
STATUS_SUCCESS : STATUS_NO_MORE_FILES;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FileFullDirectoryInformation:
|
|
{
|
|
PFILE_FULL_DIR_INFORMATION pFullDirInfo = (PFILE_FULL_DIR_INFORMATION) Buffer;
|
|
CopySize = sizeof( FILE_FULL_DIR_INFORMATION );
|
|
if ( *pLengthRemaining >= CopySize )
|
|
{
|
|
RtlZeroMemory( pFullDirInfo, CopySize );
|
|
pFullDirInfo->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
pFullDirInfo->FileNameLength = sizeof( WCHAR );
|
|
pFullDirInfo->FileName[0] = L'.';
|
|
*pLengthRemaining -= CopySize;
|
|
Status = RxContext->QueryDirectory.InitialQuery ?
|
|
STATUS_SUCCESS : STATUS_NO_MORE_FILES;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FileBothDirectoryInformation:
|
|
{
|
|
PFILE_BOTH_DIR_INFORMATION pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION) Buffer;
|
|
CopySize = sizeof( FILE_BOTH_DIR_INFORMATION );
|
|
if ( *pLengthRemaining >= CopySize )
|
|
{
|
|
RtlZeroMemory( pBothDirInfo, CopySize );
|
|
pBothDirInfo->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
pBothDirInfo->FileNameLength = sizeof( WCHAR );
|
|
pBothDirInfo->FileName[0] = L'.';
|
|
pBothDirInfo->ShortNameLength = sizeof( WCHAR );
|
|
pBothDirInfo->ShortName[0] = L'.';
|
|
*pLengthRemaining -= CopySize;
|
|
Status = RxContext->QueryDirectory.InitialQuery ?
|
|
STATUS_SUCCESS : STATUS_NO_MORE_FILES;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FileNamesInformation:
|
|
{
|
|
PFILE_NAMES_INFORMATION pNamesDirInfo = (PFILE_NAMES_INFORMATION) Buffer;
|
|
CopySize = sizeof( FILE_NAMES_INFORMATION );
|
|
if ( *pLengthRemaining >= CopySize )
|
|
{
|
|
RtlZeroMemory( pNamesDirInfo, CopySize );
|
|
pNamesDirInfo->FileNameLength = sizeof( WCHAR );
|
|
pNamesDirInfo->FileName[0] = L'.';
|
|
*pLengthRemaining -= CopySize;
|
|
Status = RxContext->QueryDirectory.InitialQuery ?
|
|
STATUS_SUCCESS : STATUS_NO_MORE_FILES;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
RxDbgTrace( 0, Dbg, ("NulMRxQueryDirectory: Invalid FS information class\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
DbgPrint("NulMRxQueryDirectory \n");
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NulMRxQueryVolumeInformation(
|
|
IN OUT PRX_CONTEXT RxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries the volume information
|
|
|
|
Arguments:
|
|
|
|
pRxContext - the RDBSS context
|
|
|
|
FsInformationClass - the kind of Fs information desired.
|
|
|
|
pBuffer - the buffer for copying the information
|
|
|
|
pBufferLength - the buffer length ( set to buffer length on input and set
|
|
to the remaining length on output)
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
RxCaptureFcb;
|
|
|
|
ULONG RemainingLength = RxContext->Info.LengthRemaining;
|
|
FS_INFORMATION_CLASS FsInformationClass = RxContext->Info.FsInformationClass;
|
|
PVOID OriginalBuffer = RxContext->Info.Buffer;
|
|
UNICODE_STRING ustrVolume;
|
|
ULONG BytesToCopy;
|
|
|
|
RxTraceEnter("NulMRxQueryVolumeInformation");
|
|
|
|
switch( FsInformationClass ) {
|
|
case FileFsVolumeInformation:
|
|
{
|
|
PFILE_FS_VOLUME_INFORMATION pVolInfo = (PFILE_FS_VOLUME_INFORMATION) OriginalBuffer;
|
|
|
|
if(RemainingLength < sizeof(FILE_FS_VOLUME_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
RtlZeroMemory( pVolInfo, sizeof(FILE_FS_VOLUME_INFORMATION) );
|
|
pVolInfo->VolumeCreationTime.QuadPart = 0;
|
|
pVolInfo->VolumeSerialNumber = 0xBABAFACE;
|
|
pVolInfo->SupportsObjects = FALSE;
|
|
RtlInitUnicodeString( &ustrVolume, L"NULMRX" );
|
|
|
|
RemainingLength -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
|
|
|
|
if (RemainingLength >= (ULONG)ustrVolume.Length) {
|
|
BytesToCopy = ustrVolume.Length;
|
|
} else {
|
|
BytesToCopy = RemainingLength;
|
|
}
|
|
|
|
RtlCopyMemory( &pVolInfo->VolumeLabel[0], (PVOID)ustrVolume.Buffer, BytesToCopy );
|
|
|
|
RemainingLength -= BytesToCopy;
|
|
pVolInfo->VolumeLabelLength = BytesToCopy;
|
|
|
|
RxContext->Info.LengthRemaining = RemainingLength;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
DbgPrint("FileFsVolumeInformation\n");
|
|
}
|
|
break;
|
|
|
|
case FileFsLabelInformation:
|
|
DbgPrint("FileFsLabelInformation\n");
|
|
break;
|
|
|
|
case FileFsSizeInformation:
|
|
DbgPrint("FileFsSizeInformation\n");
|
|
break;
|
|
|
|
case FileFsDeviceInformation:
|
|
DbgPrint("FileFsDeviceInformation\n");
|
|
break;
|
|
|
|
case FileFsAttributeInformation:
|
|
{
|
|
PFILE_FS_ATTRIBUTE_INFORMATION pAttribInfo =
|
|
(PFILE_FS_ATTRIBUTE_INFORMATION) OriginalBuffer;
|
|
|
|
if(RemainingLength < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(pAttribInfo, sizeof(FILE_FS_ATTRIBUTE_INFORMATION));
|
|
|
|
pAttribInfo->FileSystemAttributes = 0;
|
|
pAttribInfo->MaximumComponentNameLength = 32;
|
|
|
|
RemainingLength -= FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[0]);
|
|
|
|
RtlInitUnicodeString( &ustrVolume, L"SampleFS" );
|
|
|
|
BytesToCopy = RemainingLength;
|
|
if(RemainingLength >= ustrVolume.Length)
|
|
{
|
|
BytesToCopy = ustrVolume.Length;
|
|
}
|
|
|
|
pAttribInfo->FileSystemNameLength = BytesToCopy;
|
|
|
|
RtlCopyMemory( pAttribInfo->FileSystemName, (PVOID)ustrVolume.Buffer, BytesToCopy );
|
|
RemainingLength -= BytesToCopy;
|
|
|
|
RxContext->Info.LengthRemaining = RemainingLength;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
DbgPrint("FileFsAttributeInformation\n");
|
|
}
|
|
break;
|
|
|
|
case FileFsControlInformation:
|
|
DbgPrint("FileFsControlInformation\n");
|
|
break;
|
|
|
|
case FileFsFullSizeInformation:
|
|
DbgPrint("FileFsFullSizeInformation\n");
|
|
break;
|
|
|
|
case FileFsObjectIdInformation:
|
|
DbgPrint("FileFsObjectIdInformation\n");
|
|
break;
|
|
|
|
case FileFsMaximumInformation:
|
|
DbgPrint("FileFsMaximumInformation\n");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
RxTraceLeave(Status);
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
NulMRxSetVolumeInformation(
|
|
IN OUT PRX_CONTEXT pRxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the volume information
|
|
|
|
Arguments:
|
|
|
|
pRxContext - the RDBSS context
|
|
|
|
FsInformationClass - the kind of Fs information desired.
|
|
|
|
pBuffer - the buffer for copying the information
|
|
|
|
BufferLength - the buffer length
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
DbgPrint("NulMRxSetVolumeInformation \n");
|
|
return(Status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NulMRxQueryFileInformation(
|
|
IN PRX_CONTEXT RxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a query file info. Only the NT-->NT path is implemented.
|
|
|
|
The NT-->NT path works by just remoting the call basically without further ado.
|
|
|
|
Arguments:
|
|
|
|
RxContext - the RDBSS context
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
ULONG RemainingLength = RxContext->Info.LengthRemaining;
|
|
RxCaptureFcb;
|
|
FILE_INFORMATION_CLASS FunctionalityRequested =
|
|
RxContext->Info.FileInformationClass;
|
|
PFILE_STANDARD_INFORMATION pFileStdInfo =
|
|
(PFILE_STANDARD_INFORMATION) RxContext->Info.Buffer;
|
|
|
|
RxTraceEnter("NulMRxQueryFileInformation");
|
|
|
|
switch( FunctionalityRequested ) {
|
|
case FileBasicInformation:
|
|
if(RemainingLength < sizeof(FILE_BASIC_INFORMATION)) {
|
|
break;
|
|
}
|
|
RemainingLength -= sizeof(FILE_BASIC_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case FileInternalInformation:
|
|
if(RemainingLength < sizeof(FILE_INTERNAL_INFORMATION)) {
|
|
break;
|
|
}
|
|
RemainingLength -= sizeof(FILE_INTERNAL_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case FileEaInformation:
|
|
if(RemainingLength < sizeof(FILE_EA_INFORMATION)) {
|
|
break;
|
|
}
|
|
RemainingLength -= sizeof(FILE_EA_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case FileStandardInformation:
|
|
|
|
if(RemainingLength < sizeof(FILE_STANDARD_INFORMATION)) {
|
|
break;
|
|
}
|
|
|
|
RxDbgTrace(0, Dbg, ("FileSize is %d AllocationSize is %d\n",
|
|
pFileStdInfo->EndOfFile.LowPart,pFileStdInfo->AllocationSize.LowPart));
|
|
//(RxContext->CurrentIrp)->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
|
|
RemainingLength -= sizeof(FILE_STANDARD_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
RxContext->Info.LengthRemaining = RemainingLength;
|
|
|
|
RxTraceLeave(Status);
|
|
return(Status);
|
|
}
|
|
|
|
NTSTATUS
|
|
NulMRxSetFileInformation(
|
|
IN PRX_CONTEXT RxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a set file info. Only the NT-->NT path is implemented.
|
|
|
|
The NT-->NT path works by just remoting the call basically without further ado.
|
|
|
|
Arguments:
|
|
|
|
RxContext - the RDBSS context
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
RxCaptureFcb;
|
|
ULONG BufferLength = RxContext->Info.Length;
|
|
FILE_INFORMATION_CLASS FunctionalityRequested =
|
|
RxContext->Info.FileInformationClass;
|
|
PFILE_END_OF_FILE_INFORMATION pEndOfFileInfo =
|
|
(PFILE_END_OF_FILE_INFORMATION) RxContext->Info.Buffer;
|
|
LARGE_INTEGER NewAllocationSize;
|
|
|
|
RxTraceEnter("NulMRxSetFileInformation");
|
|
|
|
switch( FunctionalityRequested ) {
|
|
case FileBasicInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FileBasicInformation\n"));
|
|
|
|
if(BufferLength < sizeof(FILE_BASIC_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
|
|
case FileDispositionInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FileDispositionInformation\n"));
|
|
|
|
if(BufferLength < sizeof(FILE_DISPOSITION_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
|
|
case FilePositionInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FilePositionInformation\n"));
|
|
|
|
if(BufferLength < sizeof(FILE_POSITION_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
|
|
case FileAllocationInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FileAllocationInformation\n"));
|
|
RxDbgTrace(0, Dbg, ("AllocSize is %d AllocSizeHigh is %d\n",
|
|
pEndOfFileInfo->EndOfFile.LowPart,pEndOfFileInfo->EndOfFile.HighPart));
|
|
|
|
if(BufferLength < sizeof(FILE_ALLOCATION_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case FileEndOfFileInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FileSize is %d FileSizeHigh is %d\n",
|
|
capFcb->Header.AllocationSize.LowPart,capFcb->Header.AllocationSize.HighPart));
|
|
if(BufferLength < sizeof(FILE_END_OF_FILE_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( pEndOfFileInfo->EndOfFile.QuadPart >
|
|
capFcb->Header.AllocationSize.QuadPart ) {
|
|
|
|
Status = NulMRxExtendFile(
|
|
RxContext,
|
|
&pEndOfFileInfo->EndOfFile,
|
|
&NewAllocationSize
|
|
);
|
|
|
|
RxDbgTrace(0, Dbg, ("AllocSize is %d AllocSizeHigh is %d\n",
|
|
NewAllocationSize.LowPart,NewAllocationSize.HighPart));
|
|
|
|
//
|
|
// Change the file allocation
|
|
//
|
|
capFcb->Header.AllocationSize.QuadPart = NewAllocationSize.QuadPart;
|
|
} else {
|
|
Status = NulMRxTruncateFile(
|
|
RxContext,
|
|
&pEndOfFileInfo->EndOfFile,
|
|
&NewAllocationSize
|
|
);
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case FileRenameInformation:
|
|
|
|
RxDbgTrace(0, Dbg, ("FileRenameInformation\n"));
|
|
if(BufferLength < sizeof(FILE_RENAME_INFORMATION))
|
|
{
|
|
break;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
RxTraceLeave(Status);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NulMRxSetFileInformationAtCleanup(
|
|
IN PRX_CONTEXT RxContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the file information on cleanup. the old rdr just swallows this operation (i.e.
|
|
it doesn't generate it). we are doing the same..........
|
|
|
|
Arguments:
|
|
|
|
pRxContext - the RDBSS context
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The return status for the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
return(Status);
|
|
}
|
|
|