/*
 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
 * Copyright (c) 2009, 2010, 2011, 2014 Your File System, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice,
 *   this list of conditions and the following disclaimer in the
 *   documentation
 *   and/or other materials provided with the distribution.
 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
 *   nor the names of their contributors may be used to endorse or promote
 *   products derived from this software without specific prior written
 *   permission from Kernel Drivers, LLC and Your File System, Inc.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

//
// File: AFSFileInfo.cpp
//

#include "AFSCommon.h"

//
// Function: AFSQueryFileInfo
//
// Description:
//
//      This function is the dispatch handler for the IRP_MJ_QUERY_FILE_INFORMATION request
//
// Return:
//
//      A status is returned for the function
//

NTSTATUS
AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                  IN PIRP Irp)
{

    UNREFERENCED_PARAMETER(LibDeviceObject);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    BOOLEAN bReleaseMain = FALSE;
    LONG lLength = 0;
    FILE_INFORMATION_CLASS stFileInformationClass;
    GUID stAuthGroup;
    PVOID pBuffer;

    __try
    {

        //
        // Determine the type of request this request is
        //

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( pFcb == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryFileInfo Attempted access (%p) when pFcb == NULL\n",
                          Irp));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        lLength = (LONG)pIrpSp->Parameters.QueryFile.Length;
        stFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;
        pBuffer = Irp->AssociatedIrp.SystemBuffer;

        if ( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
        {

            RtlZeroMemory( &stAuthGroup,
                           sizeof( GUID));

            AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
                                     (ULONGLONG)PsGetCurrentThreadId(),
                                     &stAuthGroup);

            ntStatus = AFSVerifyEntry( &stAuthGroup,
				       pCcb->DirectoryCB,
				       FALSE);

            if ( NT_SUCCESS( ntStatus))
            {

		AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
			      AFS_TRACE_LEVEL_VERBOSE,
			      "AFSQueryFileInfo FID %08lX-%08lX-%08lX-%08lX Clearing Verify Flag\n",
			      pFcb->ObjectInformation->FileId.Cell,
			      pFcb->ObjectInformation->FileId.Volume,
			      pFcb->ObjectInformation->FileId.Vnode,
			      pFcb->ObjectInformation->FileId.Unique));

                ClearFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
            }
            else
            {

                ntStatus = STATUS_SUCCESS;
            }
        }

        //
        // Grab the main shared right off the bat
        //

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSQueryFileInfo Acquiring Fcb lock %p SHARED %08lX\n",
                      &pFcb->NPFcb->Resource,
                      PsGetCurrentThread()));

        AFSAcquireShared( &pFcb->NPFcb->Resource,
                          TRUE);

        bReleaseMain = TRUE;

        //
        // Don't allow requests against IOCtl nodes
        //

        if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSQueryFileInfo Processing request against SpecialShare Fcb\n"));

            ntStatus = AFSProcessShareQueryInfo( Irp,
                                                 pFcb,
                                                 pCcb);

            try_return( ntStatus);
        }
        else if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSQueryFileInfo request against PIOCtl Fcb\n"));

            ntStatus = AFSProcessPIOCtlQueryInfo( Irp,
                                                  pFcb,
                                                  pCcb,
                                                  &lLength);

            try_return( ntStatus);
        }

        else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSQueryFileInfo request against Invalid Fcb\n"));

            try_return( ntStatus = STATUS_ACCESS_DENIED);
        }

        //
        // Process the request
        //

        switch( stFileInformationClass)
        {

            case FileAllInformation:
            {

                PFILE_ALL_INFORMATION pAllInfo;

                //
                //  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.
                //

                pAllInfo = (PFILE_ALL_INFORMATION)pBuffer;

                ntStatus = AFSQueryBasicInfo( Irp,
                                              pCcb->DirectoryCB,
                                              &pAllInfo->BasicInformation,
                                              &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

                ntStatus = AFSQueryStandardInfo( Irp,
                                                 pCcb->DirectoryCB,
                                                 &pAllInfo->StandardInformation,
                                                 &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

                ntStatus = AFSQueryInternalInfo( Irp,
                                                 pFcb,
                                                 &pAllInfo->InternalInformation,
                                                 &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

                ntStatus = AFSQueryEaInfo( Irp,
                                           pCcb->DirectoryCB,
                                           &pAllInfo->EaInformation,
                                           &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

		//
		// We skip setting AccessInformation since this is set by the IO Mgr prior
		// to sending this request to the file system
		//

		if( lLength < sizeof( FILE_ACCESS_INFORMATION))
		{
		    try_return( ntStatus = STATUS_INFO_LENGTH_MISMATCH);
		}

		lLength -= sizeof( FILE_ACCESS_INFORMATION);

                ntStatus = AFSQueryPositionInfo( Irp,
                                                 pFcb,
                                                 &pAllInfo->PositionInformation,
                                                 &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

		//
		// We skip setting ModeInformation and AlignmentInformation since this is set by the IO Mgr prior
		// to sending this request to the file system
		//

		if( lLength < sizeof( FILE_MODE_INFORMATION))
		{
		    try_return( ntStatus = STATUS_INFO_LENGTH_MISMATCH);
		}

		lLength -= sizeof( FILE_MODE_INFORMATION);

		if( lLength < sizeof( FILE_ALIGNMENT_INFORMATION))
		{
		    try_return( ntStatus = STATUS_INFO_LENGTH_MISMATCH);
		}

		lLength -= sizeof( FILE_ALIGNMENT_INFORMATION);

		//
		// Populate the name information
		//

                ntStatus = AFSQueryNameInfo( Irp,
                                             pCcb->DirectoryCB,
                                             &pAllInfo->NameInformation,
                                             &lLength);

                if( !NT_SUCCESS( ntStatus))
                {

                    try_return( ntStatus);
                }

                break;
            }

            case FileBasicInformation:
            {

                ntStatus = AFSQueryBasicInfo( Irp,
                                              pCcb->DirectoryCB,
                                              (PFILE_BASIC_INFORMATION)pBuffer,
                                              &lLength);

                break;
            }

            case FileStandardInformation:
            {

                ntStatus = AFSQueryStandardInfo( Irp,
                                                 pCcb->DirectoryCB,
                                                 (PFILE_STANDARD_INFORMATION)pBuffer,
                                                 &lLength);

                break;
            }

            case FileInternalInformation:
            {

                ntStatus = AFSQueryInternalInfo( Irp,
                                                 pFcb,
                                                 (PFILE_INTERNAL_INFORMATION)pBuffer,
                                                 &lLength);

                break;
            }

            case FileEaInformation:
            {

                ntStatus = AFSQueryEaInfo( Irp,
                                           pCcb->DirectoryCB,
                                           (PFILE_EA_INFORMATION)pBuffer,
                                           &lLength);

                break;
            }

            case FilePositionInformation:
            {

                ntStatus = AFSQueryPositionInfo( Irp,
                                      pFcb,
                                      (PFILE_POSITION_INFORMATION)pBuffer,
                                      &lLength);

                break;
            }

            case FileNormalizedNameInformation:
            case FileNameInformation:
            {

                ntStatus = AFSQueryNameInfo( Irp,
                                  pCcb->DirectoryCB,
                                  (PFILE_NAME_INFORMATION)pBuffer,
                                  &lLength);

                break;
            }

            case FileAlternateNameInformation:
            {

                ntStatus = AFSQueryShortNameInfo( Irp,
                                       pCcb->DirectoryCB,
                                       (PFILE_NAME_INFORMATION)pBuffer,
                                       &lLength);

                break;
            }

            case FileNetworkOpenInformation:
            {

                ntStatus = AFSQueryNetworkInfo( Irp,
                                     pCcb->DirectoryCB,
                                     (PFILE_NETWORK_OPEN_INFORMATION)pBuffer,
                                     &lLength);

                break;
            }

            case FileStreamInformation:
            {

                ntStatus = AFSQueryStreamInfo( Irp,
                                               pCcb->DirectoryCB,
                                               (FILE_STREAM_INFORMATION *)pBuffer,
                                               &lLength);

                break;
            }


            case FileAttributeTagInformation:
            {

                ntStatus = AFSQueryAttribTagInfo( Irp,
                                                  pCcb->DirectoryCB,
                                                  (FILE_ATTRIBUTE_TAG_INFORMATION *)pBuffer,
                                                  &lLength);

                break;
            }

            case FileRemoteProtocolInformation:
            {

                    ntStatus = AFSQueryRemoteProtocolInfo( Irp,
                                                           pCcb->DirectoryCB,
                                                           (FILE_REMOTE_PROTOCOL_INFORMATION *)pBuffer,
                                                           &lLength);

                break;
            }

            case FileNetworkPhysicalNameInformation:
            {

                ntStatus = AFSQueryPhysicalNameInfo( Irp,
                                                     pCcb->DirectoryCB,
                                                     (FILE_NETWORK_PHYSICAL_NAME_INFORMATION *)pBuffer,
                                                     &lLength);

                break;
            }

            default:
            {
                ntStatus = STATUS_INVALID_PARAMETER;
                break;
            }
        }

try_exit:

        Irp->IoStatus.Information = pIrpSp->Parameters.QueryFile.Length - lLength;

        if( bReleaseMain)
        {

            AFSReleaseResource( &pFcb->NPFcb->Resource);
        }

        if( !NT_SUCCESS( ntStatus) &&
            ntStatus != STATUS_INVALID_PARAMETER &&
            ntStatus != STATUS_BUFFER_OVERFLOW)
        {

            if( pCcb != NULL &&
                pCcb->DirectoryCB != NULL)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSQueryFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileId.Cell,
                              pFcb->ObjectInformation->FileId.Volume,
                              pFcb->ObjectInformation->FileId.Vnode,
                              pFcb->ObjectInformation->FileId.Unique,
                              ntStatus));
            }
        }
    }
    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgTrace(( 0,
                      0,
                      "EXCEPTION - AFSQueryFileInfo\n"));

        AFSDumpTraceFilesFnc();

        ntStatus = STATUS_UNSUCCESSFUL;

        if( bReleaseMain)
        {

            AFSReleaseResource( &pFcb->NPFcb->Resource);
        }
    }

    AFSCompleteRequest( Irp,
                        ntStatus);

    return ntStatus;
}

//
// Function: AFSSetFileInfo
//
// Description:
//
//      This function is the dispatch handler for the IRP_MJ_SET_FILE_INFORMATION request
//
// Return:
//
//      A status is returned for the function
//

NTSTATUS
AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                IN PIRP Irp)
{

    UNREFERENCED_PARAMETER(LibDeviceObject);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    FILE_INFORMATION_CLASS FileInformationClass;
    BOOLEAN bCanQueueRequest = FALSE;
    PFILE_OBJECT pFileObject = NULL;
    BOOLEAN bReleaseMain = FALSE;
    BOOLEAN bUpdateFileInfo = FALSE;
    AFSFileID stParentFileId;

    __try
    {

        pFileObject = pIrpSp->FileObject;

        pFcb = (AFSFcb *)pFileObject->FsContext;
        pCcb = (AFSCcb *)pFileObject->FsContext2;

        if( pFcb == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileInfo Attempted access (%p) when pFcb == NULL\n",
                          Irp));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        bCanQueueRequest = !(IoIsOperationSynchronous( Irp) | (KeGetCurrentIrql() != PASSIVE_LEVEL));
        FileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;

        //
        // Grab the Fcb EXCL
        //

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSSetFileInfo Acquiring Fcb lock %p EXCL %08lX\n",
                      &pFcb->NPFcb->Resource,
                      PsGetCurrentThread()));

        AFSAcquireExcl( &pFcb->NPFcb->Resource,
                        TRUE);

        bReleaseMain = TRUE;

        //
        // Don't allow requests against IOCtl nodes
        //

        if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileInfo Failing request against PIOCtl Fcb\n"));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }
        else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileInfo Processing request against SpecialShare Fcb\n"));

            ntStatus = AFSProcessShareSetInfo( Irp,
                                               pFcb,
                                               pCcb);

            try_return( ntStatus);
        }

	if( FileInformationClass != FilePositionInformation &&
	    BooleanFlagOn( pFcb->ObjectInformation->VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileInfo Request failed due to read only volume\n",
                          Irp));

            try_return( ntStatus = STATUS_MEDIA_WRITE_PROTECTED);
        }

        if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB &&
            FileInformationClass != FileDispositionInformation)
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileInfo request against Invalid Fcb\n"));

            try_return( ntStatus = STATUS_ACCESS_DENIED);
        }

        //
        // Ensure rename operations are synchronous
        //

        if( FileInformationClass == FileRenameInformation)
        {

            bCanQueueRequest = FALSE;
        }

        //
        // Store away the parent fid
        //

        RtlZeroMemory( &stParentFileId,
                       sizeof( AFSFileID));

        if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
        {

            stParentFileId = pFcb->ObjectInformation->ParentFileId;
        }

        //
        // Process the request
        //

        switch( FileInformationClass)
        {

            case FileBasicInformation:
            {

                ntStatus = AFSSetBasicInfo( Irp,
					    pCcb->DirectoryCB,
					    &bUpdateFileInfo);

                break;
            }

            case FileDispositionInformation:
            {

                ntStatus = AFSSetDispositionInfo( Irp,
                                                  pCcb->DirectoryCB);

                break;
            }

            case FileRenameInformation:
            {

                ntStatus = AFSSetRenameInfo( Irp);

                break;
            }

            case FilePositionInformation:
            {

                ntStatus = AFSSetPositionInfo( Irp,
                                               pCcb->DirectoryCB);

                break;
            }

            case FileLinkInformation:
            {

                ntStatus = AFSSetFileLinkInfo( Irp);

                break;
            }

            case FileAllocationInformation:
            {

                ntStatus = AFSSetAllocationInfo( Irp,
                                                 pCcb->DirectoryCB);

                break;
            }

            case FileEndOfFileInformation:
            {

                ntStatus = AFSSetEndOfFileInfo( Irp,
                                                pCcb->DirectoryCB);

                break;
            }

            default:

                ntStatus = STATUS_INVALID_PARAMETER;

                break;
        }

try_exit:

        if( bReleaseMain)
        {

            AFSReleaseResource( &pFcb->NPFcb->Resource);
        }

        if( NT_SUCCESS( ntStatus) &&
            bUpdateFileInfo)
        {

            ntStatus = AFSUpdateFileInformation( &stParentFileId,
                                                 pFcb->ObjectInformation,
                                                 &pCcb->AuthGroup);

            if( !NT_SUCCESS( ntStatus))
            {

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                //
                // Unwind the update and fail the request
                //

                AFSUnwindFileInfo( pFcb,
                                   pCcb);

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetFileInfo Failed to send file info update to service request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileId.Cell,
                              pFcb->ObjectInformation->FileId.Volume,
                              pFcb->ObjectInformation->FileId.Vnode,
                              pFcb->ObjectInformation->FileId.Unique,
                              ntStatus));

                AFSReleaseResource( &pFcb->NPFcb->Resource);
            }
        }

        if( !NT_SUCCESS( ntStatus))
        {

            if( pCcb != NULL &&
                pCcb->DirectoryCB != NULL)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetFileInfo Failed to process request for %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileId.Cell,
                              pFcb->ObjectInformation->FileId.Volume,
                              pFcb->ObjectInformation->FileId.Vnode,
                              pFcb->ObjectInformation->FileId.Unique,
                              ntStatus));
            }
        }
    }
    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgTrace(( 0,
                      0,
                      "EXCEPTION - AFSSetFileInfo\n"));

        AFSDumpTraceFilesFnc();

        ntStatus = STATUS_UNSUCCESSFUL;

        if( bReleaseMain)
        {

            AFSReleaseResource( &pFcb->NPFcb->Resource);
        }
    }

    AFSCompleteRequest( Irp,
                        ntStatus);

    return ntStatus;
}

//
// Function: AFSQueryBasicInfo
//
// Description:
//
//      This function is the handler for the query basic information request
//
// Return:
//
//      A status is returned for the function
//

NTSTATUS
AFSQueryBasicInfo( IN PIRP Irp,
                   IN AFSDirectoryCB *DirectoryCB,
                   IN OUT PFILE_BASIC_INFORMATION Buffer,
                   IN OUT PLONG Length)
{
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    ULONG ulFileAttribs = 0;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFileInfoCB stFileInfo;
    AFSDirectoryCB *pParentDirectoryCB = NULL;
    UNICODE_STRING uniParentPath;

    if( *Length >= sizeof( FILE_BASIC_INFORMATION))
    {

        RtlZeroMemory( Buffer,
                       *Length);

        ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);

            AFSRetrieveParentPath( &pCcb->FullFileName,
                                   &uniParentPath);

            RtlZeroMemory( &stFileInfo,
                           sizeof( AFSFileInfoCB));

            //
            // Can't hold the Fcb while evaluating the path, leads to lock inversion
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            //
            // Its a reparse point regardless of whether the file attributes
            // can be retrieved for the target.
            //

            if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
            {

                ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
            }
            else
            {

                ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
            }

            if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
                                                       DirectoryCB,
                                                       &uniParentPath,
                                                       pCcb->NameArray,
                                                       &pCcb->AuthGroup,
                                                       &stFileInfo)))
            {

                if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {

                    ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
                }
            }

            AFSAcquireShared( &pFcb->NPFcb->Resource,
                              TRUE);
        }


        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSQueryBasicInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
                      &pCcb->DirectoryCB->NameInformation.FileName,
                      pFcb->ObjectInformation->FileType,
                      pFcb->ObjectInformation->FileAttributes,
                      ulFileAttribs));

        Buffer->CreationTime = DirectoryCB->ObjectInformation->CreationTime;
        Buffer->LastAccessTime = DirectoryCB->ObjectInformation->LastAccessTime;
        Buffer->LastWriteTime = DirectoryCB->ObjectInformation->LastWriteTime;
        Buffer->ChangeTime = DirectoryCB->ObjectInformation->ChangeTime;
        Buffer->FileAttributes = ulFileAttribs;

        if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
            BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
        {

            if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
            {
                Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
            }
            else
            {
                Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
            }
        }

        *Length -= sizeof( FILE_BASIC_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryStandardInfo( IN PIRP Irp,
                      IN AFSDirectoryCB *DirectoryCB,
                      IN OUT PFILE_STANDARD_INFORMATION Buffer,
                      IN OUT PLONG Length)
{

    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFileInfoCB stFileInfo;
    AFSDirectoryCB *pParentDirectoryCB = NULL;
    UNICODE_STRING uniParentPath;
    ULONG ulFileAttribs = 0;

    if( *Length >= sizeof( FILE_STANDARD_INFORMATION))
    {

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        RtlZeroMemory( Buffer,
                       *Length);

	Buffer->NumberOfLinks = DirectoryCB->ObjectInformation->Links;
        Buffer->DeletePending = BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);

	Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;

        Buffer->EndOfFile = DirectoryCB->ObjectInformation->EndOfFile;

        ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;

        if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);

            AFSRetrieveParentPath( &pCcb->FullFileName,
                                   &uniParentPath);

            RtlZeroMemory( &stFileInfo,
                           sizeof( AFSFileInfoCB));

            //
            // Can't hold the Fcb while evaluating the path, leads to lock inversion
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            //
            // Its a reparse point regardless of whether or not the
            // file attributes can be retrieved.
            //

            if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
            {

                ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
            }
            else
            {

                ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
            }

            if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
                                                       DirectoryCB,
                                                       &uniParentPath,
                                                       pCcb->NameArray,
                                                       &pCcb->AuthGroup,
                                                       &stFileInfo)))
            {

                if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {

                    ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
                }
            }

            AFSAcquireShared( &pFcb->NPFcb->Resource,
                              TRUE);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSQueryStandardInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
                      &pCcb->DirectoryCB->NameInformation.FileName,
                      pFcb->ObjectInformation->FileType,
                      pFcb->ObjectInformation->FileAttributes,
                      ulFileAttribs));

        Buffer->Directory = BooleanFlagOn( ulFileAttribs, FILE_ATTRIBUTE_DIRECTORY);

        *Length -= sizeof( FILE_STANDARD_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryInternalInfo( IN PIRP Irp,
                      IN AFSFcb *Fcb,
                      IN OUT PFILE_INTERNAL_INFORMATION Buffer,
                      IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Irp);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;

    if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
    {

        Buffer->IndexNumber.HighPart = Fcb->ObjectInformation->FileId.Vnode;

        Buffer->IndexNumber.LowPart = Fcb->ObjectInformation->FileId.Unique;

        *Length -= sizeof( FILE_INTERNAL_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryEaInfo( IN PIRP Irp,
                IN AFSDirectoryCB *DirectoryCB,
                IN OUT PFILE_EA_INFORMATION Buffer,
                IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Irp);
    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;

    RtlZeroMemory( Buffer,
                   *Length);

    if( *Length >= sizeof( FILE_EA_INFORMATION))
    {

        Buffer->EaSize = 0;

        *Length -= sizeof( FILE_EA_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryPositionInfo( IN PIRP Irp,
                      IN AFSFcb *Fcb,
                      IN OUT PFILE_POSITION_INFORMATION Buffer,
                      IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Fcb);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    if( *Length >= sizeof( FILE_POSITION_INFORMATION))
    {

        RtlZeroMemory( Buffer,
                       *Length);

        Buffer->CurrentByteOffset.QuadPart = pIrpSp->FileObject->CurrentByteOffset.QuadPart;

        *Length -= sizeof( FILE_POSITION_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryNameInfo( IN PIRP Irp,
                  IN AFSDirectoryCB *DirectoryCB,
                  IN OUT PFILE_NAME_INFORMATION Buffer,
                  IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

    pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

    if( *Length >= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
    {

	RtlZeroMemory( Buffer,
		       *Length);

	*Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

	ntStatus = AFSGetFullFileName( pFcb,
				       pCcb,
				       &Buffer->FileNameLength,
				       Buffer->FileName,
				       Length);
    }

    return ntStatus;
}

NTSTATUS
AFSQueryShortNameInfo( IN PIRP Irp,
                       IN AFSDirectoryCB *DirectoryCB,
                       IN OUT PFILE_NAME_INFORMATION Buffer,
                       IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Irp);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    ULONG ulCopyLength = 0;

    RtlZeroMemory( Buffer,
                   *Length);

    if( DirectoryCB->NameInformation.ShortNameLength == 0)
    {

        //
        // The short name IS the long name
        //

        if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
        {

            if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
            {

                ulCopyLength = (LONG)DirectoryCB->NameInformation.FileName.Length;

                ntStatus = STATUS_SUCCESS;
            }
            else
            {

                ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

                ntStatus = STATUS_BUFFER_OVERFLOW;
            }

            Buffer->FileNameLength = DirectoryCB->NameInformation.FileName.Length;

            *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

            if( ulCopyLength > 0)
            {

                RtlCopyMemory( Buffer->FileName,
                               DirectoryCB->NameInformation.FileName.Buffer,
                               ulCopyLength);

                *Length -= ulCopyLength;
            }
        }
    }
    else
    {

        if( *Length >= (LONG)FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
        {

            if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)DirectoryCB->NameInformation.FileName.Length))
            {

                ulCopyLength = (LONG)DirectoryCB->NameInformation.ShortNameLength;

                ntStatus = STATUS_SUCCESS;
            }
            else
            {

                ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

                ntStatus = STATUS_BUFFER_OVERFLOW;
            }

            Buffer->FileNameLength = DirectoryCB->NameInformation.ShortNameLength;

            *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

            if( ulCopyLength > 0)
            {

                RtlCopyMemory( Buffer->FileName,
                               DirectoryCB->NameInformation.ShortName,
                               Buffer->FileNameLength);

                *Length -= ulCopyLength;
            }
        }
    }

    return ntStatus;
}

NTSTATUS
AFSQueryNetworkInfo( IN PIRP Irp,
                     IN AFSDirectoryCB *DirectoryCB,
                     IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
                     IN OUT PLONG Length)
{

    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFileInfoCB stFileInfo;
    AFSDirectoryCB *pParentDirectoryCB = NULL;
    UNICODE_STRING uniParentPath;
    ULONG ulFileAttribs = 0;

    RtlZeroMemory( Buffer,
                   *Length);

    if( *Length >= sizeof( FILE_NETWORK_OPEN_INFORMATION))
    {

        ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);

            AFSRetrieveParentPath( &pCcb->FullFileName,
                                   &uniParentPath);

            RtlZeroMemory( &stFileInfo,
                           sizeof( AFSFileInfoCB));

            //
            // Can't hold the Fcb while evaluating the path, leads to lock inversion
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            //
            // Its a reparse point regardless of whether the file attributes
            // can be retrieved for the target.
            //

            if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
            {

                ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
            }
            else
            {

                ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
            }

            if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
                                                       DirectoryCB,
                                                       &uniParentPath,
                                                       pCcb->NameArray,
                                                       &pCcb->AuthGroup,
                                                       &stFileInfo)))
            {

                if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {

                    ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
                }
            }

            AFSAcquireShared( &pFcb->NPFcb->Resource,
                              TRUE);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSQueryNetworkInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
                      &pCcb->DirectoryCB->NameInformation.FileName,
                      pFcb->ObjectInformation->FileType,
                      pFcb->ObjectInformation->FileAttributes,
                      ulFileAttribs));

        Buffer->CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;
        Buffer->LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;
        Buffer->LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;
        Buffer->ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;

        Buffer->AllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;
        Buffer->EndOfFile.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;

        Buffer->FileAttributes = ulFileAttribs;

        if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
            BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
        {

            if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
            {

                Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
            }
            else
            {

                Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
            }
        }

        *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION);

	ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryStreamInfo( IN PIRP Irp,
                    IN AFSDirectoryCB *DirectoryCB,
                    IN OUT FILE_STREAM_INFORMATION *Buffer,
                    IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Irp);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    ULONG ulCopyLength = 0;

    if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
    {

        RtlZeroMemory( Buffer,
                       *Length);

        Buffer->NextEntryOffset = 0;


        if( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
        {

            if( *Length >= (LONG)(FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName) + 14))  // ::$DATA
            {

                ulCopyLength = 14;

                ntStatus = STATUS_SUCCESS;
            }
            else
            {

                ulCopyLength = *Length - FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);

                ntStatus = STATUS_BUFFER_OVERFLOW;
            }

            Buffer->StreamNameLength = 14; // ::$DATA

            Buffer->StreamSize.QuadPart = DirectoryCB->ObjectInformation->EndOfFile.QuadPart;

            Buffer->StreamAllocationSize.QuadPart = DirectoryCB->ObjectInformation->AllocationSize.QuadPart;

            *Length -= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName);

            if( ulCopyLength > 0)
            {

                RtlCopyMemory( Buffer->StreamName,
                               L"::$DATA",
                               ulCopyLength);

                *Length -= ulCopyLength;
            }
        }
        else
        {

            Buffer->StreamNameLength = 0;       // No stream for a directory

            // The response size is zero

            ntStatus = STATUS_SUCCESS;
        }
    }

    return ntStatus;
}

NTSTATUS
AFSQueryAttribTagInfo( IN PIRP Irp,
                       IN AFSDirectoryCB *DirectoryCB,
                       IN OUT FILE_ATTRIBUTE_TAG_INFORMATION *Buffer,
                       IN OUT PLONG Length)
{

    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFileInfoCB stFileInfo;
    AFSDirectoryCB *pParentDirectoryCB = NULL;
    UNICODE_STRING uniParentPath;
    ULONG ulFileAttribs = 0;

    if( *Length >= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION))
    {

        RtlZeroMemory( Buffer,
                       *Length);

        ulFileAttribs = DirectoryCB->ObjectInformation->FileAttributes;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pParentDirectoryCB = AFSGetParentEntry( pCcb->NameArray);

            AFSRetrieveParentPath( &pCcb->FullFileName,
                                   &uniParentPath);

            RtlZeroMemory( &stFileInfo,
                           sizeof( AFSFileInfoCB));

            //
            // Can't hold the Fcb while evaluating the path, leads to lock inversion
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            //
            // Its a reparse point regardless of whether the file attributes
            // can be retrieved for the target.
            //

            if ( ulFileAttribs == FILE_ATTRIBUTE_NORMAL)
            {

                ulFileAttribs = FILE_ATTRIBUTE_REPARSE_POINT;
            }
            else
            {

                ulFileAttribs |= FILE_ATTRIBUTE_REPARSE_POINT;
            }

            if( NT_SUCCESS( AFSRetrieveFileAttributes( pParentDirectoryCB,
                                                       DirectoryCB,
                                                       &uniParentPath,
                                                       pCcb->NameArray,
                                                       &pCcb->AuthGroup,
                                                       &stFileInfo)))
            {

                if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {

                    ulFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
                }
            }

            AFSAcquireShared( &pFcb->NPFcb->Resource,
                              TRUE);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSAttribTagInfo %wZ Type 0x%x Attrib 0x%x -> 0x%x\n",
                      &pCcb->DirectoryCB->NameInformation.FileName,
                      pFcb->ObjectInformation->FileType,
                      pFcb->ObjectInformation->FileAttributes,
                      ulFileAttribs));

        Buffer->FileAttributes = ulFileAttribs;

        if( DirectoryCB->NameInformation.FileName.Buffer[ 0] == L'.' &&
            BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
        {

            if ( Buffer->FileAttributes != FILE_ATTRIBUTE_NORMAL)
            {

                Buffer->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
            }
            else
            {

                Buffer->FileAttributes = FILE_ATTRIBUTE_HIDDEN;
            }
        }

        if ( DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
        {

            Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
        }
        else if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
        {

            Buffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;
        }

        *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);

        ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryRemoteProtocolInfo( IN PIRP Irp,
                            IN AFSDirectoryCB *DirectoryCB,
                            IN OUT FILE_REMOTE_PROTOCOL_INFORMATION *Buffer,
                            IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(Irp);
    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;

    if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
    {

        RtlZeroMemory( Buffer,
                       *Length);

        Buffer->StructureVersion = 1;

        Buffer->StructureSize = sizeof(FILE_REMOTE_PROTOCOL_INFORMATION);

        Buffer->Protocol = WNNC_NET_OPENAFS;

        Buffer->ProtocolMajorVersion = 3;

        Buffer->ProtocolMinorVersion = 0;

        Buffer->ProtocolRevision = 0;

        *Length -= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION);

        ntStatus = STATUS_SUCCESS;
    }

    return ntStatus;
}

NTSTATUS
AFSQueryPhysicalNameInfo( IN PIRP Irp,
                          IN AFSDirectoryCB *DirectoryCB,
                          IN OUT PFILE_NETWORK_PHYSICAL_NAME_INFORMATION Buffer,
                          IN OUT PLONG Length)
{

    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_INFO_LENGTH_MISMATCH;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

    pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

    if( *Length >= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName))
    {

	RtlZeroMemory( Buffer,
		       *Length);

	*Length -= FIELD_OFFSET( FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FileName);

	ntStatus = AFSGetFullFileName( pFcb,
				       pCcb,
				       &Buffer->FileNameLength,
				       Buffer->FileName,
				       Length);
    }

    return ntStatus;
}

NTSTATUS
AFSSetBasicInfo( IN PIRP Irp,
		 IN AFSDirectoryCB *DirectoryCB,
		 OUT BOOLEAN *bUpdateFileInfo)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_BASIC_INFORMATION pBuffer;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    ULONG ulNotifyFilter = 0;
    AFSCcb *pCcb = NULL;

    __Enter
    {

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        pBuffer = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

        pCcb->FileUnwindInfo.FileAttributes = (ULONG)-1;

        if( pBuffer->FileAttributes != (ULONGLONG)0)
        {

	    //
	    // Make sure that the reparse point attribute is not modified.
	    // Fail if the RP attribute is requested but it is not
	    // already a RP.  Otherwise, ignore it.
	    //

	    if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
				 FILE_ATTRIBUTE_REPARSE_POINT) &&
		 BooleanFlagOn( pBuffer->FileAttributes,
				FILE_ATTRIBUTE_REPARSE_POINT))
	    {

		try_return( ntStatus = STATUS_INVALID_PARAMETER);
	    }

	    //
	    // Make sure that the directory attribute is not modified.
	    // Fail if the D attribute is requested but it is not
	    // already a directory.  Otherwise, ignore it.
	    //

	    if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
				 FILE_ATTRIBUTE_DIRECTORY) &&
		 BooleanFlagOn( pBuffer->FileAttributes,
				FILE_ATTRIBUTE_DIRECTORY))
	    {

		try_return( ntStatus = STATUS_INVALID_PARAMETER);
	    }

	    //
	    // Save the original value
	    //

	    pCcb->FileUnwindInfo.FileAttributes = DirectoryCB->ObjectInformation->FileAttributes;

	    if( BooleanFlagOn( pBuffer->FileAttributes, FILE_ATTRIBUTE_READONLY))
	    {

		//
		// Set the readonly flag.
		//

		if ( !BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
				     FILE_ATTRIBUTE_READONLY))
		{

		    if ( DirectoryCB->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
		    {

			DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_READONLY;
		    }
		    else
		    {

			DirectoryCB->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_READONLY;
		    }

		    ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;

		    SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
		}
	    }
	    else
	    {
		//
		// Reset the readonly flag.
		//

		if ( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes,
				    FILE_ATTRIBUTE_READONLY))
		{

		    DirectoryCB->ObjectInformation->FileAttributes &= ~FILE_ATTRIBUTE_READONLY;

		    if ( DirectoryCB->ObjectInformation->FileAttributes == 0)
		    {

			DirectoryCB->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_NORMAL;
		    }

		    ulNotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;

		    SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);
		}
	    }
        }

        pCcb->FileUnwindInfo.CreationTime.QuadPart = (ULONGLONG)-1;

        if( pBuffer->CreationTime.QuadPart != (ULONGLONG)-1 &&
            pBuffer->CreationTime.QuadPart != (ULONGLONG)0)
        {

            pCcb->FileUnwindInfo.CreationTime.QuadPart = DirectoryCB->ObjectInformation->CreationTime.QuadPart;

            DirectoryCB->ObjectInformation->CreationTime.QuadPart = pBuffer->CreationTime.QuadPart;

            ulNotifyFilter |= FILE_NOTIFY_CHANGE_CREATION;

            SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CREATE_TIME);
        }

        pCcb->FileUnwindInfo.LastAccessTime.QuadPart = (ULONGLONG)-1;

        if( pBuffer->LastAccessTime.QuadPart != (ULONGLONG)-1 &&
            pBuffer->LastAccessTime.QuadPart != (ULONGLONG)0)
        {

            pCcb->FileUnwindInfo.LastAccessTime.QuadPart = DirectoryCB->ObjectInformation->LastAccessTime.QuadPart;

            DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = pBuffer->LastAccessTime.QuadPart;

            ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;

            SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
        }

        pCcb->FileUnwindInfo.LastWriteTime.QuadPart = (ULONGLONG)-1;

        if( pBuffer->LastWriteTime.QuadPart != (ULONGLONG)-1 &&
            pBuffer->LastWriteTime.QuadPart != (ULONGLONG)0)
        {

            pCcb->FileUnwindInfo.LastWriteTime.QuadPart = DirectoryCB->ObjectInformation->LastWriteTime.QuadPart;

            DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = pBuffer->LastWriteTime.QuadPart;

            ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE;

            SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME);

	    SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);

	} else if ( pBuffer->LastWriteTime.QuadPart == (ULONGLONG)-1) {

	    SetFlag( pCcb->Flags, CCB_FLAG_LAST_WRITE_TIME_SET);
        }

        pCcb->FileUnwindInfo.ChangeTime.QuadPart = (ULONGLONG)-1;

        if( pBuffer->ChangeTime.QuadPart != (ULONGLONG)-1 &&
            pBuffer->ChangeTime.QuadPart != (ULONGLONG)0)
        {

            pCcb->FileUnwindInfo.ChangeTime.QuadPart = DirectoryCB->ObjectInformation->ChangeTime.QuadPart;

            DirectoryCB->ObjectInformation->ChangeTime.QuadPart = pBuffer->ChangeTime.QuadPart;

            ulNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;

            SetFlag( DirectoryCB->ObjectInformation->Fcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
        }

        if( ulNotifyFilter > 0)
        {

	    *bUpdateFileInfo = TRUE;

            if( BooleanFlagOn( DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
            {

                AFSObjectInfoCB * pParentObjectInfo = AFSFindObjectInfo( DirectoryCB->ObjectInformation->VolumeCB,
                                                                         &DirectoryCB->ObjectInformation->ParentFileId,
                                                                         TRUE);

                if ( pParentObjectInfo != NULL)
                {
                    AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
                                                    pCcb,
                                                    (ULONG)ulNotifyFilter,
                                                    (ULONG)FILE_ACTION_MODIFIED);

                    AFSReleaseObjectInfo( &pParentObjectInfo);
                }
            }
        }

try_exit:

        NOTHING;
    }

    return ntStatus;
}

NTSTATUS
AFSSetDispositionInfo( IN PIRP Irp,
                       IN AFSDirectoryCB *DirectoryCB)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_DISPOSITION_INFORMATION pBuffer;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;

    __Enter
    {

        pBuffer = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        //
        // Can't delete the root
        //

        if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetDispositionInfo Attempt to delete root entry\n"));

            try_return( ntStatus = STATUS_CANNOT_DELETE);
        }

        //
        // If the file is read only then do not allow the delete
        //

        if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetDispositionInfo Attempt to delete read only entry %wZ\n",
                          &DirectoryCB->NameInformation.FileName));

            try_return( ntStatus = STATUS_CANNOT_DELETE);
        }

        if( pBuffer->DeleteFile)
        {

            //
            // Check if the caller can delete the file
            //

            ntStatus = AFSNotifyDelete( DirectoryCB,
                                        &pCcb->AuthGroup,
                                        TRUE);

            if( !NT_SUCCESS( ntStatus))
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetDispositionInfo Cannot delete entry %wZ Status %08lX\n",
                              &DirectoryCB->NameInformation.FileName,
                              ntStatus));

                try_return( ntStatus);
            }

            if( pFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
            {

                //
                // Check if this is a directory that there are not currently other opens
                //

                if( pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSSetDispositionInfo Attempt to delete directory %wZ with open %u handles\n",
                                  &DirectoryCB->NameInformation.FileName,
                                  pFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount));

                    try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
                }

                //
                // Make sure the directory is enumerated before checking to see if it is empty.
                //

                if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
                {

                    AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                    TRUE);

                    if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
                    {

                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSSetDispositionInfo Enumerating parent FID %08lX-%08lX-%08lX-%08lX\n",
                                      pFcb->ObjectInformation->FileId.Cell,
                                      pFcb->ObjectInformation->FileId.Volume,
                                      pFcb->ObjectInformation->FileId.Vnode,
                                      pFcb->ObjectInformation->FileId.Unique));

                        ntStatus = AFSEnumerateDirectory( &pCcb->AuthGroup,
                                                          pFcb->ObjectInformation,
                                                          TRUE);

                        if( !NT_SUCCESS( ntStatus))
                        {

                            AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);

                            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_ERROR,
                                          "AFSSetDispositionInfo Failed to enumerate parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                                          pFcb->ObjectInformation->FileId.Cell,
                                          pFcb->ObjectInformation->FileId.Volume,
                                          pFcb->ObjectInformation->FileId.Vnode,
                                          pFcb->ObjectInformation->FileId.Unique,
                                          ntStatus));

                            try_return( ntStatus);
                        }
                    }

                    AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                }

                if( !AFSIsDirectoryEmptyForDelete( pFcb))
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSSetDispositionInfo Attempt to delete non-empty directory %wZ\n",
                                  &DirectoryCB->NameInformation.FileName));

                    try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
                }

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry  %p Name %wZ\n",
                              DirectoryCB,
                              &DirectoryCB->NameInformation.FileName));

                SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
            }
            else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
            {
                BOOLEAN bMmFlushed;

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
			      AFS_TRACE_LEVEL_VERBOSE,
			      "AFSSetDispositionInfo Acquiring Fcb lock %p EXCL %08lX\n",
			      &pFcb->NPFcb->Resource,
			      PsGetCurrentThread()));

		AFSAcquireExcl( &pFcb->NPFcb->Resource,
				TRUE);

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
                              &pFcb->NPFcb->SectionObjectResource,
                              PsGetCurrentThread()));

                AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
                                TRUE);

		__try
                {

                    //
		    // Attempt to flush any outstanding data
                    //

		    bMmFlushed = MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
						      MmFlushForDelete);

		    if ( bMmFlushed)
		    {

			//
			// Set PENDING_DELETE before CcPurgeCacheSection to avoid a
			// deadlock with Trend Micro's Enterprise anti-virus product
			// which attempts to open the file which is being deleted.
			//

			AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
				      AFS_TRACE_LEVEL_VERBOSE,
				      "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
				      DirectoryCB,
				      &DirectoryCB->NameInformation.FileName));

			SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);

			//
			// Purge the cache as well
			//

			if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
                        {

			    if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
						       NULL,
						       0,
						       TRUE))
			    {

				SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
			    }
                        }
                    }
                }
		__except( EXCEPTION_EXECUTE_HANDLER)
		{

		    bMmFlushed = FALSE;

		    ntStatus = GetExceptionCode();

		    AFSDbgTrace(( 0,
				  0,
				  "EXCEPTION - AFSSetDispositionInfo MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
				  pFcb->ObjectInformation->FileId.Cell,
				  pFcb->ObjectInformation->FileId.Volume,
				  pFcb->ObjectInformation->FileId.Vnode,
				  pFcb->ObjectInformation->FileId.Unique,
				  ntStatus));
		}

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
                              &pFcb->NPFcb->SectionObjectResource,
                              PsGetCurrentThread()));

                AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
			      AFS_TRACE_LEVEL_VERBOSE,
			      "AFSSetDispositionInfo Releasing Fcb lock %p EXCL %08lX\n",
			      &pFcb->NPFcb->Resource,
			      PsGetCurrentThread()));

		AFSReleaseResource( &pFcb->NPFcb->Resource);

                if ( !bMmFlushed)
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
                                  &DirectoryCB->NameInformation.FileName));

                    try_return( ntStatus = STATUS_CANNOT_DELETE);
                }
            }
            else if( pFcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
                     pFcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
                     pFcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
                     pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
                              DirectoryCB,
                              &DirectoryCB->NameInformation.FileName));

                SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
            }
        }
        else
        {

            ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
        }

        //
        // OK, should be good to go, set the flag in the file object
        //

        pIrpSp->FileObject->DeletePending = pBuffer->DeleteFile;

try_exit:

        NOTHING;
    }

    return ntStatus;
}

NTSTATUS
AFSSetFileLinkInfo( IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
    PFILE_OBJECT pSrcFileObj = NULL;
    PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
    AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
    AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
    AFSObjectInfoCB *pSrcObject = NULL;
    AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
    UNICODE_STRING uniSourceName, uniTargetName;
    UNICODE_STRING uniFullTargetName, uniTargetParentName;
    BOOLEAN bCommonParent = FALSE;
    AFSDirectoryCB *pTargetDirEntry = NULL;
    AFSDirectoryCB *pNewTargetDirEntry = NULL;
    ULONG ulTargetCRC;
    BOOLEAN bTargetEntryExists = FALSE;
    LONG lCount;
    BOOLEAN bReleaseTargetDirLock = FALSE;
    ULONG ulNotificationAction = 0, ulNotifyFilter = 0;

    __Enter
    {

        pSrcFileObj = pIrpSp->FileObject;

        pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
        pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;

        pSrcObject = pSrcFcb->ObjectInformation;

        if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
        {

            pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
                                                  &pSrcObject->ParentFileId,
                                                  TRUE);
        }

        if( pSrcParentObject == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileLinkInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));

            ASSERT( FALSE);

            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

        pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

        //
        // Perform some basic checks to ensure FS integrity
        //

        if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n"));

            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

        if( pTargetFileObj == NULL)
        {

            if ( pFileLinkInfo->RootDirectory)
            {

                //
                // The target directory is provided by HANDLE
                // RootDirectory is only set when the target directory is not the same
                // as the source directory.
                //
                // AFS only supports hard links within a single directory.
                //
                // The IOManager should translate any Handle to a FileObject for us.
                // However, the failure to receive a FileObject is treated as a fatal
                // error.
                //

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
                              &pSrcCcb->DirectoryCB->NameInformation.FileName));

                try_return( ntStatus = STATUS_INVALID_PARAMETER);
            }
            else
            {

                uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;

                uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;

                AFSRetrieveFinalComponent( &uniFullTargetName,
                                           &uniTargetName);

                AFSRetrieveParentPath( &uniFullTargetName,
                                       &uniTargetParentName);

                if ( uniTargetParentName.Length == 0)
                {

                    //
                    // This is a simple rename. Here the target directory is the same as the source parent directory
                    // and the name is retrieved from the system buffer information
                    //

                    pTargetParentObject = pSrcParentObject;
                }
                else
                {
                    //
                    // uniTargetParentName contains the directory the renamed object
                    // will be moved to.  Must obtain the TargetParentObject.
                    //

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSSetFileLinkInfo Attempt to link  %wZ to alternate directory %wZ (NOT_SAME_DEVICE)\n",
                                  &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                  &uniFullTargetName));

                    try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
                }
            }

            pTargetDcb = pTargetParentObject->Fcb;
        }
        else
        {

            //
            // So here we have the target directory taken from the targetfile object
            //

            pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;

            pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;

            pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;

            //
            // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
            // it is only the target component of the rename operation
            //

            uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
        }

        //
        // The quick check to see if they are self linking.
        // Do the names match? Only do this where the parent directories are
        // the same
        //

        if( pTargetParentObject == pSrcParentObject)
        {

            if( FsRtlAreNamesEqual( &uniTargetName,
                                    &uniSourceName,
                                    FALSE,
                                    NULL))
            {
                try_return( ntStatus = STATUS_SUCCESS);
            }

            bCommonParent = TRUE;
        }
        else
        {

            //
            // We do not allow cross-volume hard links
            //

            if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetFileLinkInfo Attempt to link to different volume %wZ\n",
                              &pSrcCcb->DirectoryCB->NameInformation.FileName));

                try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
            }
        }

        ulTargetCRC = AFSGenerateCRC( &uniTargetName,
                                      FALSE);

        AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
                        TRUE);

        bReleaseTargetDirLock = TRUE;

        AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
                                        ulTargetCRC,
                                        &pTargetDirEntry);

        if( pTargetDirEntry == NULL)
        {

            //
            // Missed so perform a case insensitive lookup
            //

            ulTargetCRC = AFSGenerateCRC( &uniTargetName,
                                          TRUE);

            AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
                                              ulTargetCRC,
                                              &pTargetDirEntry);

	    if ( pTargetDirEntry == NULL)
	    {

		if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
		     RtlIsNameLegalDOS8Dot3( &uniTargetName,
					     NULL,
					     NULL))
		{
		    //
		    // Try the short name
		    //
		    AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
						ulTargetCRC,
						&pTargetDirEntry);
		}
	    }
	    else
	    {
		//
		// Here we have a match on the case insensitive lookup for the name. If there
		// Is more than one link entry for this node then fail the lookup request
		//

		if( !BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
		    pTargetDirEntry->CaseInsensitiveList.fLink != NULL)
		{

		    pTargetDirEntry = NULL;

		    try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
		}
	    }
        }

        //
        // Increment our ref count on the dir entry
        //

        if( pTargetDirEntry != NULL)
        {

            ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
                    AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));

            lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileLinkInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);

            if( !pFileLinkInfo->ReplaceIfExists)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetFileLinkInfo Attempt to link with target collision %wZ Target %wZ\n",
                              &pSrcCcb->DirectoryCB->NameInformation.FileName,
                              &pTargetDirEntry->NameInformation.FileName));

                try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
            }

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          lCount));

            //
            // Pull the directory entry from the parent
            //

            AFSRemoveDirNodeFromParent( pTargetParentObject,
                                        pTargetDirEntry,
                                        FALSE);

            bTargetEntryExists = TRUE;
        }
        else
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileLinkInfo Target does NOT exist, normal linking\n"));
        }

        //
        // OK, this is a simple rename. Issue the rename
        // request to the service.
        //

        ntStatus = AFSNotifyHardLink( pSrcObject,
                                      &pSrcCcb->AuthGroup,
                                      pSrcParentObject,
                                      pTargetDcb->ObjectInformation,
                                      pSrcCcb->DirectoryCB,
                                      &uniTargetName,
                                      pFileLinkInfo->ReplaceIfExists,
                                      &pNewTargetDirEntry);

        if( ntStatus != STATUS_REPARSE &&
            !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
                          &pSrcCcb->DirectoryCB->NameInformation.FileName,
                          &uniTargetName,
                          ntStatus));

            try_return( ntStatus);
        }

        if ( ntStatus != STATUS_REPARSE)
        {

            AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
                                    pNewTargetDirEntry,
                                    TRUE);
        }

        //
        // Send notification for the target link file
        //

        if( bTargetEntryExists || pNewTargetDirEntry)
        {

            ulNotificationAction = FILE_ACTION_MODIFIED;
        }
        else
        {

            ulNotificationAction = FILE_ACTION_ADDED;
        }

        AFSFsRtlNotifyFullReportChange( pTargetParentObject,
                                        pSrcCcb,
                                        (ULONG)ulNotifyFilter,
                                        (ULONG)ulNotificationAction);

      try_exit:

        if( !NT_SUCCESS( ntStatus))
        {

            if( bTargetEntryExists)
            {

                AFSInsertDirectoryNode( pTargetParentObject,
                                        pTargetDirEntry,
                                        FALSE);
            }
        }

        if( pTargetDirEntry != NULL)
        {

            //
            // Release DirOpenReferenceCount obtained above
            //

            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);
        }

        if( pNewTargetDirEntry != NULL)
        {

            //
            // Release DirOpenReferenceCount obtained from AFSNotifyHardLink
            //

            lCount = InterlockedDecrement( &pNewTargetDirEntry->DirOpenReferenceCount);

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetFileLinkInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pNewTargetDirEntry->NameInformation.FileName,
                          pNewTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);
        }

        if( bReleaseTargetDirLock)
        {

            AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
        }

        if ( pSrcParentObject != NULL)
        {

            AFSReleaseObjectInfo( &pSrcParentObject);
        }

        //
        // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
        // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
        //

        pTargetParentObject = NULL;
    }

    return ntStatus;
}

NTSTATUS
AFSSetRenameInfo( IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
    AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
    PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
    PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
    PFILE_OBJECT pTargetParentFileObj = NULL;
    PFILE_RENAME_INFORMATION pRenameInfo = NULL;
    UNICODE_STRING uniTargetName, uniSourceName, uniTargetParentName;
    BOOLEAN bReplaceIfExists = FALSE;
    UNICODE_STRING uniShortName;
    AFSDirectoryCB *pTargetDirEntry = NULL;
    ULONG ulTargetCRC = 0;
    BOOLEAN bTargetEntryExists = FALSE;
    AFSObjectInfoCB *pSrcObject = NULL;
    AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
    AFSFileID stNewFid;
    ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
    UNICODE_STRING uniFullTargetName;
    BOOLEAN bCommonParent = FALSE;
    BOOLEAN bReleaseTargetDirLock = FALSE;
    BOOLEAN bReleaseSourceDirLock = FALSE;
    BOOLEAN bDereferenceTargetParentObject = FALSE;
    PERESOURCE  pSourceDirLock = NULL;
    LONG lCount;

    __Enter
    {

        bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;

        pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

        pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
        pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;

        pSrcObject = pSrcFcb->ObjectInformation;

        if ( BooleanFlagOn( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
        {

            pSrcParentObject = AFSFindObjectInfo( pSrcObject->VolumeCB,
                                                  &pSrcObject->ParentFileId,
                                                  TRUE);
        }

        if( pSrcParentObject == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Unable to resolve SrcParentObject (INVALID_PARAMETER)\n"));

            ASSERT( FALSE);

            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

        //
        // Perform some basic checks to ensure FS integrity
        //

        if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
        {

            //
            // Can't rename the root directory
            //

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Attempt to rename root entry\n"));

            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

        if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
        {

            //
            // If there are any open children then fail the rename
            //

            if( pSrcObject->Specific.Directory.ChildOpenHandleCount > 0)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
                              &pSrcCcb->DirectoryCB->NameInformation.FileName));

                try_return( ntStatus = STATUS_ACCESS_DENIED);
            }
        }


        //
        // Extract off the final component name from the Fcb
        //

        uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
        uniSourceName.MaximumLength = uniSourceName.Length;

        uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;

        //
        // Resolve the target fileobject
        //

        if( pTargetFileObj == NULL)
        {

            if ( pRenameInfo->RootDirectory)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetRenameInfo Handle provided but no FileObject ntStatus INVALID_PARAMETER\n"));

                try_return( ntStatus = STATUS_INVALID_PARAMETER);
            }
            else
            {

                uniFullTargetName.Length = (USHORT)pRenameInfo->FileNameLength;

                uniFullTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;

                AFSRetrieveFinalComponent( &uniFullTargetName,
                                           &uniTargetName);

                AFSRetrieveParentPath( &uniFullTargetName,
                                       &uniTargetParentName);

                if ( uniTargetParentName.Length == 0)
                {

                    //
                    // This is a simple rename. Here the target directory is the same as the source parent directory
                    // and the name is retrieved from the system buffer information
                    //

                    pTargetParentObject = pSrcParentObject;
                }
                else
                {
                    //
                    // uniTargetParentName contains the directory the renamed object
                    // will be moved to.  Must obtain the TargetParentObject.
                    //

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSSetRenameInfo Attempt to move %wZ to %wZ -- not yet supported (NOT_SAME_DEVICE)\n",
                                  &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                  &uniFullTargetName));

                    try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
                }
            }

            pTargetDcb = pTargetParentObject->Fcb;
        }
        else
        {

            //
            // So here we have the target directory taken from the targetfile object
            //

            pTargetDcb = (AFSFcb *)pTargetFileObj->FsContext;

            pTargetDirCcb = (AFSCcb *)pTargetFileObj->FsContext2;

            pTargetParentObject = (AFSObjectInfoCB *)pTargetDcb->ObjectInformation;

            //
            // Grab the target name which we setup in the IRP_MJ_CREATE handler. By how we set this up
            // it is only the target component of the rename operation
            //

            uniTargetName = *((PUNICODE_STRING)&pTargetFileObj->FileName);
        }

        //
        // The quick check to see if they are not really performing a rename
        // Do the names match? Only do this where the parent directories are
        // the same
        //

        if( pTargetParentObject == pSrcParentObject)
        {

            if( FsRtlAreNamesEqual( &uniTargetName,
                                    &uniSourceName,
                                    FALSE,
                                    NULL))
            {
                try_return( ntStatus = STATUS_SUCCESS);
            }

            bCommonParent = TRUE;
        }
        else
        {

            bCommonParent = FALSE;
        }

        //
        // We do not allow cross-volume renames to occur
        //

        if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
                          &pSrcCcb->DirectoryCB->NameInformation.FileName));

            try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
        }

        ulTargetCRC = AFSGenerateCRC( &uniTargetName,
                                      FALSE);

        AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
                        TRUE);

        bReleaseTargetDirLock = TRUE;

        if( pTargetParentObject != pSrcParentObject)
        {
            AFSAcquireExcl( pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
                            TRUE);

            bReleaseSourceDirLock = TRUE;

            pSourceDirLock = pSrcParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock;
        }

        AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
                                        ulTargetCRC,
                                        &pTargetDirEntry);

        if( pTargetDirEntry == NULL)
        {

            //
            // Missed so perform a case insensitive lookup
            //

            ulTargetCRC = AFSGenerateCRC( &uniTargetName,
                                          TRUE);

            AFSLocateCaseInsensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
                                              ulTargetCRC,
                                              &pTargetDirEntry);

	    if ( pTargetDirEntry == NULL)
	    {

		if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
		     RtlIsNameLegalDOS8Dot3( &uniTargetName,
					     NULL,
					     NULL))
		{
		    //
		    // Try the short name
		    //
		    AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
						ulTargetCRC,
						&pTargetDirEntry);
		}
	    }
	    else
	    {
		//
		// Here we have a match on the case insensitive lookup for the name. If there
		// Is more than one link entry for this node then fail the lookup request
		//

		if( !BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
		    pTargetDirEntry->CaseInsensitiveList.fLink != NULL)
		{

		    pTargetDirEntry = NULL;

		    try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
		}
	    }
        }

        //
        // Increment our ref count on the dir entry
        //

        if( pTargetDirEntry != NULL)
        {

            ASSERT( BooleanFlagOn( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
                    AFSIsEqualFID( &pTargetParentObject->FileId, &pTargetDirEntry->ObjectInformation->ParentFileId));

            lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Increment count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);

	    //
	    // Need to acquire the ObjectInfoLock while checking for the Fcb OpenRefCount so we don't race with
	    // a tear down worker thread on the Fcb
	    //

	    AFSAcquireShared( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock,
			      TRUE);

	    //
	    // Check there are no current opens on the target
	    //

	    if( BooleanFlagOn( pTargetDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY) ||
		( pTargetDirEntry->ObjectInformation->Fcb != NULL &&
		  pTargetDirEntry->ObjectInformation->Fcb->OpenReferenceCount != 0))
	    {

		//
		// Return the correct error code
		//

		if( BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
		{
		    ntStatus = STATUS_DELETE_PENDING;
		}
		else
		{
		    ntStatus = STATUS_ACCESS_DENIED;
		}

		AFSReleaseResource( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock);

		AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
			      AFS_TRACE_LEVEL_ERROR,
			      "AFSSetRenameInfo Attempt to rename %s Target %wZ Status %08lX\n",
			      BooleanFlagOn( pTargetDirEntry->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_READONLY)?"ReadOnly":"Open",
			      &pTargetDirEntry->NameInformation.FileName,
			      ntStatus));

		try_return( ntStatus);
	    }

	    AFSReleaseResource( &pTargetDirEntry->ObjectInformation->NonPagedInfo->ObjectInfoLock);

            if( !bReplaceIfExists)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
                              &pSrcCcb->DirectoryCB->NameInformation.FileName,
                              &pTargetDirEntry->NameInformation.FileName));

                try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
            }

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          lCount));

            //
            // Pull the directory entry from the parent
            //

            AFSRemoveDirNodeFromParent( pTargetParentObject,
                                        pTargetDirEntry,
                                        FALSE);

            bTargetEntryExists = TRUE;
        }
        else
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Target does NOT exist, normal rename\n"));
        }

        //
        // We need to remove the DirEntry from the parent node, update the index
        // and reinsert it into the parent tree. Note that for entries with the
        // same parent we do not pull the node from the enumeration list
        //

        AFSRemoveDirNodeFromParent( pSrcParentObject,
                                    pSrcCcb->DirectoryCB,
                                    !bCommonParent);

        //
        // OK, this is a simple rename. Issue the rename
        // request to the service.
        //

        ntStatus = AFSNotifyRename( pSrcObject,
                                    &pSrcCcb->AuthGroup,
                                    pSrcParentObject,
                                    pTargetDcb->ObjectInformation,
                                    pSrcCcb->DirectoryCB,
                                    &uniTargetName,
                                    &stNewFid);

        if( !NT_SUCCESS( ntStatus))
        {

            //
            // Attempt to re-insert the directory entry
            //

            AFSInsertDirectoryNode( pSrcParentObject,
                                    pSrcCcb->DirectoryCB,
                                    !bCommonParent);

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
                          &pSrcCcb->DirectoryCB->NameInformation.FileName,
                          &uniTargetName,
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // Set the notification up for the source file
        //

        if( pSrcParentObject == pTargetParentObject &&
            !bTargetEntryExists)
        {

            ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
        }
        else
        {

            ulNotificationAction = FILE_ACTION_REMOVED;
        }

        if( pSrcObject->FileType == AFS_FILE_TYPE_DIRECTORY)
        {

            ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
        }
        else
        {

            ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
        }

        AFSFsRtlNotifyFullReportChange( pSrcParentObject,
                                        pSrcCcb,
                                        (ULONG)ulNotifyFilter,
                                        (ULONG)ulNotificationAction);

        //
        // Update the name in the dir entry.
        //

        ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
                                          &uniTargetName);

        if( !NT_SUCCESS( ntStatus))
        {

            //
            // Attempt to re-insert the directory entry
            //

            AFSInsertDirectoryNode( pSrcParentObject,
                                    pSrcCcb->DirectoryCB,
                                    !bCommonParent);

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSSetRenameInfo Failed update of dir entry %wZ to target %wZ Status %08lX\n",
                          &pSrcCcb->DirectoryCB->NameInformation.FileName,
                          &uniTargetName,
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // Update the object information block, if needed
        //

        if( !AFSIsEqualFID( &pSrcObject->FileId,
                            &stNewFid))
        {

            AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
                            TRUE);

            //
            // Remove the old information entry
            //

            AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
                                &pSrcObject->TreeEntry);

            RtlCopyMemory( &pSrcObject->FileId,
                           &stNewFid,
                           sizeof( AFSFileID));

            //
            // Insert the entry into the new object table.
            //

            pSrcObject->TreeEntry.HashIndex = AFSCreateLowIndex( &pSrcObject->FileId);

            if( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead == NULL)
            {

                pSrcObject->VolumeCB->ObjectInfoTree.TreeHead = &pSrcObject->TreeEntry;
            }
            else
            {

                if ( !NT_SUCCESS( AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
                                                     &pSrcObject->TreeEntry)))
                {

                    //
                    // Lost a race, an ObjectInfo object already exists for this FID.
                    // Let this copy be garbage collected.
                    //

                    ClearFlag( pSrcObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
                }
            }

            AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
        }

        //
        // Update the hash values for the name trees.
        //

        pSrcCcb->DirectoryCB->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                                                                 FALSE);

        pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                                                                   TRUE);

        if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
            pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0 &&
            !RtlIsNameLegalDOS8Dot3( &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                     NULL,
                                     NULL))
        {

            uniShortName.Length = pSrcCcb->DirectoryCB->NameInformation.ShortNameLength;
            uniShortName.MaximumLength = uniShortName.Length;
            uniShortName.Buffer = pSrcCcb->DirectoryCB->NameInformation.ShortName;

            pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
                                                                                           TRUE);

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Initialized short name hash for %wZ longname %wZ\n",
                          &uniShortName,
                          &pSrcCcb->DirectoryCB->NameInformation.FileName));
        }
        else
        {

            pSrcCcb->DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
        }

        if( !bCommonParent)
        {

            //
            // Update the file index for the object in the new parent
            //

            pSrcCcb->DirectoryCB->FileIndex = (ULONG)InterlockedIncrement( &pTargetParentObject->Specific.Directory.DirectoryNodeHdr.ContentIndex);
        }

        //
        // Re-insert the directory entry
        //

        AFSInsertDirectoryNode( pTargetParentObject,
                                pSrcCcb->DirectoryCB,
                                !bCommonParent);

        //
        // Update the parent pointer in the source object if they are different
        //

        if( pSrcParentObject != pTargetParentObject)
        {

            lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenHandleCount);

            lCount = InterlockedDecrement( &pSrcParentObject->Specific.Directory.ChildOpenReferenceCount);

            lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);

            lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);


            //
            // Guaranteed to be in the same volume
            //

            AFSAcquireExcl( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock,
                            TRUE);

            lCount = AFSObjectInfoIncrement( pTargetParentObject,
                                             AFS_OBJECT_REFERENCE_CHILD);

            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Increment count on parent object %p Cnt %d\n",
                          pTargetParentObject,
                          lCount));

            lCount = AFSObjectInfoDecrement( pSrcParentObject,
                                             AFS_OBJECT_REFERENCE_CHILD);

            AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Decrement count on parent object %p Cnt %d\n",
                          pSrcParentObject,
                          lCount));

            pSrcObject->ParentFileId = pTargetParentObject->FileId;

            SetFlag( pSrcObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID);

            AFSReleaseResource( pSrcParentObject->VolumeCB->ObjectInfoTree.TreeLock);

            ulNotificationAction = FILE_ACTION_ADDED;
        }
        else
        {

            ulNotificationAction = FILE_ACTION_RENAMED_NEW_NAME;
        }

        //
        // Now update the notification for the target file
        //

        AFSFsRtlNotifyFullReportChange( pTargetParentObject,
                                        pSrcCcb,
                                        (ULONG)ulNotifyFilter,
                                        (ULONG)ulNotificationAction);

        //
        // If we performed the rename of the target because it existed, we now need to
        // delete the tmp target we created above
        //

        if( bTargetEntryExists)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
                          pTargetDirEntry,
                          &pTargetDirEntry->NameInformation.FileName));

            SetFlag( pTargetDirEntry->Flags, AFS_DIR_ENTRY_DELETED);

            //
            // Try and purge the cache map if this is a file
            //

            if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
                pTargetDirEntry->ObjectInformation->Fcb != NULL &&
                pTargetDirEntry->DirOpenReferenceCount > 1)
            {

                pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
            }

            ASSERT( pTargetDirEntry->DirOpenReferenceCount > 0);

            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount); // The count we added above

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);

            if( lCount == 0 &&
                pTargetDirEntry->NameArrayReferenceCount <= 0)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
                              pTargetDirEntry,
                              &pTargetDirEntry->NameInformation.FileName));

                AFSDeleteDirEntry( pTargetParentObject,
                                   &pTargetDirEntry);
            }

            pTargetDirEntry = NULL;

            if ( pTargetFcb != NULL)
            {

                //
                // Do not hold TreeLocks across the MmForceSectionClosed() call as
                // it can deadlock with Trend Micro's TmPreFlt!TmpQueryFullName
                //

                if( bReleaseTargetDirLock)
                {
                    AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);

                    bReleaseTargetDirLock = FALSE;
                }

                if( bReleaseSourceDirLock)
                {

                    AFSReleaseResource( pSourceDirLock);

                    bReleaseSourceDirLock = FALSE;
                }

                //
                // MmForceSectionClosed() can eventually call back into AFSCleanup
                // which will need to acquire Fcb->Resource exclusively.  Failure
                // to obtain it here before holding the SectionObjectResource will
                // permit the locks to be obtained out of order risking a deadlock.
                //

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetRenameInfo Acquiring Fcb lock %p EXCL %08lX\n",
                              &pTargetFcb->NPFcb->Resource,
                              PsGetCurrentThread()));

                AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
                                TRUE);

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetRenameInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
                              &pTargetFcb->NPFcb->SectionObjectResource,
                              PsGetCurrentThread()));

                AFSAcquireExcl( &pTargetFcb->NPFcb->SectionObjectResource,
                                TRUE);

		__try
		{

		    //
		    // Close the section in the event it was mapped
		    //

		    if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
					       TRUE))
		    {

			AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
				      AFS_TRACE_LEVEL_ERROR,
				      "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
				      &uniTargetName));
		    }
		}
		__except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
                {

		    ntStatus = GetExceptionCode();

		    AFSDbgTrace(( 0,
				  0,
				  "EXCEPTION - AFSSetRenameInfo MmForceSectionClosed failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
				  pTargetFcb->ObjectInformation->FileId.Cell,
				  pTargetFcb->ObjectInformation->FileId.Volume,
				  pTargetFcb->ObjectInformation->FileId.Vnode,
				  pTargetFcb->ObjectInformation->FileId.Unique,
				  ntStatus));
                }

		AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetRenameInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
                              &pTargetFcb->NPFcb->SectionObjectResource,
                              PsGetCurrentThread()));

                AFSReleaseResource( &pTargetFcb->NPFcb->SectionObjectResource);

                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSSetRenameInfo Releasing Fcb lock %p EXCL %08lX\n",
                              &pTargetFcb->NPFcb->Resource,
                              PsGetCurrentThread()));

                AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
            }
        }

try_exit:

        if( !NT_SUCCESS( ntStatus))
        {

            if( bTargetEntryExists)
            {

                ASSERT( pTargetParentObject != NULL);

                AFSInsertDirectoryNode( pTargetParentObject,
                                        pTargetDirEntry,
                                        FALSE);
            }
        }

        if( pTargetDirEntry != NULL)
        {

            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);

            AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetRenameInfo Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
                          &pTargetDirEntry->NameInformation.FileName,
                          pTargetDirEntry,
                          pSrcCcb,
                          lCount));

            ASSERT( lCount >= 0);
        }

        if( bReleaseTargetDirLock)
        {

            AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
        }

        if( bReleaseSourceDirLock)
        {

            AFSReleaseResource( pSourceDirLock);
        }

        if ( bDereferenceTargetParentObject)
        {

            ObDereferenceObject( pTargetParentFileObj);
        }

        if ( pSrcParentObject != NULL)
        {

            AFSReleaseObjectInfo( &pSrcParentObject);
        }

        //
        // No need to release pTargetParentObject as it is either a copy of pSrcParentObject
        // or (AFSFcb *)pTargetFileObj->FsContext->ObjectInformation
        //

        pTargetParentObject = NULL;
    }

    return ntStatus;
}

NTSTATUS
AFSSetPositionInfo( IN PIRP Irp,
                    IN AFSDirectoryCB *DirectoryCB)
{
    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_POSITION_INFORMATION pBuffer;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    pBuffer = (PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

    pIrpSp->FileObject->CurrentByteOffset.QuadPart = pBuffer->CurrentByteOffset.QuadPart;

    return ntStatus;
}

NTSTATUS
AFSSetAllocationInfo( IN PIRP Irp,
                      IN AFSDirectoryCB *DirectoryCB)
{
    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_ALLOCATION_INFORMATION pBuffer;
    BOOLEAN bReleasePaging = FALSE;
    BOOLEAN bTellCc = FALSE;
    BOOLEAN bTellService = FALSE;
    BOOLEAN bUserMapped = FALSE;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    PFILE_OBJECT pFileObject = pIrpSp->FileObject;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    LARGE_INTEGER liSaveAlloc;
    LARGE_INTEGER liSaveFileSize;
    LARGE_INTEGER liSaveVDL;

    pBuffer = (PFILE_ALLOCATION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

    pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

    pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

    //
    // save values to put back
    //
    liSaveAlloc = pFcb->Header.AllocationSize;
    liSaveFileSize = pFcb->Header.FileSize;
    liSaveVDL = pFcb->Header.ValidDataLength;

    if( pFcb->Header.AllocationSize.QuadPart == pBuffer->AllocationSize.QuadPart ||
        pIrpSp->Parameters.SetFile.AdvanceOnly)
    {
        return STATUS_SUCCESS ;
    }

    if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
    {

	AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSSetAllocationInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
                      &pFcb->NPFcb->SectionObjectResource,
                      PsGetCurrentThread()));

        AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
                        TRUE);

	__try
	{

	    bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
						 &pBuffer->AllocationSize);
	}
	__except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
	{

	    bUserMapped = FALSE;

	    ntStatus = GetExceptionCode();

	    AFSDbgTrace(( 0,
			  0,
			  "EXCEPTION - AFSSetAllocationInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
			  pFcb->ObjectInformation->FileId.Cell,
			  pFcb->ObjectInformation->FileId.Volume,
			  pFcb->ObjectInformation->FileId.Vnode,
			  pFcb->ObjectInformation->FileId.Unique,
			  ntStatus));
	}

	AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSSetAllocationInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
                      &pFcb->NPFcb->SectionObjectResource,
                      PsGetCurrentThread()));

        AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);

        //
        // Truncating the file
        //
        if ( bUserMapped)
        {

            ntStatus = STATUS_USER_MAPPED_FILE ;
        }
        else
        {

            //
            // If this is a truncation we need to grab the paging IO resource.
            //

            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                          &pFcb->NPFcb->PagingResource,
                          PsGetCurrentThread()));

            AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
                            TRUE);

            bReleasePaging = TRUE;

            //
            // Must drop the Fcb Resource.  When changing the file size
            // a deadlock can occur with Trend Micro's filter if the file
            // size is set to zero.
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            pFcb->Header.AllocationSize = pBuffer->AllocationSize;

            pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;

            //
            // Tell Cc that Allocation is moved.
            //
            bTellCc = TRUE;

            if( pFcb->Header.FileSize.QuadPart > pBuffer->AllocationSize.QuadPart)
            {
                //
                // We are pulling the EOF back as well so we need to tell
                // the service.
                //
                bTellService = TRUE;

                pFcb->Header.FileSize = pBuffer->AllocationSize;

                pFcb->ObjectInformation->EndOfFile = pBuffer->AllocationSize;
            }

        }
    }
    else
    {
        //
        // Tell Cc if allocation is increased.
        //

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                      &pFcb->NPFcb->PagingResource,
                      PsGetCurrentThread()));

        AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
                        TRUE);

        bReleasePaging = TRUE;

        //
        // Must drop the Fcb Resource.  When changing the file size
        // a deadlock can occur with Trend Micro's filter if the file
        // size is set to zero.
        //

        AFSReleaseResource( &pFcb->NPFcb->Resource);

        bTellCc = pBuffer->AllocationSize.QuadPart > pFcb->Header.AllocationSize.QuadPart;

        pFcb->Header.AllocationSize = pBuffer->AllocationSize;

        pFcb->ObjectInformation->AllocationSize = pBuffer->AllocationSize;
    }

    //
    // Now Tell the server if we have to
    //
    if (bTellService)
    {

        ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));

        ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
                                             pFcb->ObjectInformation,
                                             &pCcb->AuthGroup);
    }

    if (NT_SUCCESS(ntStatus))
    {
        //
        // Trim extents if we told the service - the update has done an implicit
        // trim at the service.
        //
        if (bTellService)
        {
            AFSTrimExtents( pFcb,
                            &pFcb->Header.FileSize);
        }

        KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);

        SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);

        if (bTellCc &&
            CcIsFileCached( pFileObject))
        {
            CcSetFileSizes( pFileObject,
                            (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);
        }

	//
	// Mark the file as modified so as to reflect the change into the last write on close.
	//
	SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
    }
    else
    {
        //
        // Put the saved values back
        //
        pFcb->Header.ValidDataLength = liSaveVDL;
        pFcb->Header.FileSize = liSaveFileSize;
        pFcb->Header.AllocationSize = liSaveAlloc;
        pFcb->ObjectInformation->EndOfFile = liSaveFileSize;
        pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
    }

    if( bReleasePaging)
    {

        AFSReleaseResource( &pFcb->NPFcb->PagingResource);

        AFSAcquireExcl( &pFcb->NPFcb->Resource,
                        TRUE);
    }

    return ntStatus;
}

NTSTATUS
AFSSetEndOfFileInfo( IN PIRP Irp,
                     IN AFSDirectoryCB *DirectoryCB)
{
    UNREFERENCED_PARAMETER(DirectoryCB);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PFILE_END_OF_FILE_INFORMATION pBuffer;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    PFILE_OBJECT pFileObject = pIrpSp->FileObject;
    LARGE_INTEGER liSaveSize;
    LARGE_INTEGER liSaveVDL;
    LARGE_INTEGER liSaveAlloc;
    BOOLEAN bModified = FALSE;
    BOOLEAN bReleasePaging = FALSE;
    BOOLEAN bTruncated = FALSE;
    BOOLEAN bUserMapped = FALSE;
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;

    pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

    pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

    pBuffer = (PFILE_END_OF_FILE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

    liSaveSize = pFcb->Header.FileSize;
    liSaveAlloc = pFcb->Header.AllocationSize;
    liSaveVDL = pFcb->Header.ValidDataLength;

    if( pFcb->Header.FileSize.QuadPart != pBuffer->EndOfFile.QuadPart &&
        !pIrpSp->Parameters.SetFile.AdvanceOnly)
    {

        if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
        {

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetEndOfFileInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
                          &pFcb->NPFcb->SectionObjectResource,
                          PsGetCurrentThread()));

            AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
                            TRUE);

	    __try
	    {

		bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
						     &pBuffer->EndOfFile);
	    }
	    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
	    {

		bUserMapped = FALSE;

		ntStatus = GetExceptionCode();

		AFSDbgTrace(( 0,
			      0,
			      "EXCEPTION - AFSSetEndOfFileInfo MmCanFileBeTruncated failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
			      pFcb->ObjectInformation->FileId.Cell,
			      pFcb->ObjectInformation->FileId.Volume,
			      pFcb->ObjectInformation->FileId.Vnode,
			      pFcb->ObjectInformation->FileId.Unique,
			      ntStatus));
	    }

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSSetEndOfFileInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
                          &pFcb->NPFcb->SectionObjectResource,
                          PsGetCurrentThread()));

            AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);

            // Truncating the file
            if ( bUserMapped)
            {

                ntStatus = STATUS_USER_MAPPED_FILE;
            }
            else
            {

                //
                // If this is a truncation we need to grab the paging
                // IO resource.
                //
                AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
			      "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                              &pFcb->NPFcb->PagingResource,
                              PsGetCurrentThread()));

                AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
                                TRUE);

                bReleasePaging = TRUE;

                //
                // Must drop the Fcb Resource.  When changing the file size
                // a deadlock can occur with Trend Micro's filter if the file
                // size is set to zero.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                pFcb->Header.AllocationSize = pBuffer->EndOfFile;

                pFcb->Header.FileSize = pBuffer->EndOfFile;

                pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;

                pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;

                if( pFcb->Header.ValidDataLength.QuadPart > pFcb->Header.FileSize.QuadPart)
                {

                    pFcb->Header.ValidDataLength = pFcb->Header.FileSize;
                }

                bTruncated = TRUE;

                bModified = TRUE;
            }
        }
        else
        {

            //
            // extending the file, move EOF
            //

            //
            // If this is a truncation we need to grab the paging
            // IO resource.
            //
            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
			  "AFSSetEndOfFileInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                          &pFcb->NPFcb->PagingResource,
                          PsGetCurrentThread()));

            AFSAcquireExcl( &pFcb->NPFcb->PagingResource,
                            TRUE);

            bReleasePaging = TRUE;

            //
            // Must drop the Fcb Resource.  When changing the file size
            // a deadlock can occur with Trend Micro's filter if the file
            // size is set to zero.
            //

            AFSReleaseResource( &pFcb->NPFcb->Resource);

            pFcb->Header.FileSize = pBuffer->EndOfFile;

            pFcb->ObjectInformation->EndOfFile = pBuffer->EndOfFile;

            if (pFcb->Header.FileSize.QuadPart > pFcb->Header.AllocationSize.QuadPart)
            {
                //
                // And Allocation as needed.
                //
                pFcb->Header.AllocationSize = pBuffer->EndOfFile;

                pFcb->ObjectInformation->AllocationSize = pBuffer->EndOfFile;
            }

            bModified = TRUE;
        }
    }

    if (bModified)
    {

        KeQuerySystemTime( &pFcb->ObjectInformation->ChangeTime);

        SetFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED | AFS_FCB_FLAG_UPDATE_CHANGE_TIME);

        //
        // Tell the server
        //

        ASSERT( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID));

        ntStatus = AFSUpdateFileInformation( &pFcb->ObjectInformation->ParentFileId,
                                             pFcb->ObjectInformation,
                                             &pCcb->AuthGroup);

        if( NT_SUCCESS(ntStatus))
        {
            //
            // We are now good to go so tell CC.
            //
            CcSetFileSizes( pFileObject,
                            (PCC_FILE_SIZES)&pFcb->Header.AllocationSize);

            //
            // And give up those extents
            //
            if( bTruncated)
            {

                AFSTrimExtents( pFcb,
                                &pFcb->Header.FileSize);
            }

	    //
	    // Mark the file as modified so as to reflect the change into the last write on close.
	    //
	    SetFlag( pFileObject->Flags, FO_FILE_MODIFIED);
        }
        else
        {
            pFcb->Header.ValidDataLength = liSaveVDL;
            pFcb->Header.FileSize = liSaveSize;
            pFcb->Header.AllocationSize = liSaveAlloc;
            pFcb->ObjectInformation->EndOfFile = liSaveSize;
            pFcb->ObjectInformation->AllocationSize = liSaveAlloc;
        }
    }

    if( bReleasePaging)
    {

        AFSReleaseResource( &pFcb->NPFcb->PagingResource);

        AFSAcquireExcl( &pFcb->NPFcb->Resource,
                        TRUE);
    }

    return ntStatus;
}

NTSTATUS
AFSProcessShareSetInfo( IN IRP *Irp,
                        IN AFSFcb *Fcb,
                        IN AFSCcb *Ccb)
{

    UNREFERENCED_PARAMETER(Fcb);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    FILE_INFORMATION_CLASS ulFileInformationClass;
    void *pPipeInfo = NULL;

    __Enter
    {
        ulFileInformationClass = pIrpSp->Parameters.SetFile.FileInformationClass;

        AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessShareSetInfo On pipe %wZ Class %08lX\n",
                      &Ccb->DirectoryCB->NameInformation.FileName,
                      ulFileInformationClass));

        pPipeInfo = AFSLockSystemBuffer( Irp,
                                         pIrpSp->Parameters.SetFile.Length);

        if( pPipeInfo == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSProcessShareSetInfo Failed to lock buffer on pipe %wZ\n",
                          &Ccb->DirectoryCB->NameInformation.FileName));

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        //
        // Send the request to the service
        //

        ntStatus = AFSNotifySetPipeInfo( Ccb,
                                         (ULONG)ulFileInformationClass,
                                         pIrpSp->Parameters.SetFile.Length,
                                         pPipeInfo);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSProcessShareSetInfo Failed to send request to service on pipe %wZ Status %08lX\n",
                          &Ccb->DirectoryCB->NameInformation.FileName,
                          ntStatus));

            try_return( ntStatus);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessShareSetInfo Completed request on pipe %wZ Class %08lX\n",
                      &Ccb->DirectoryCB->NameInformation.FileName,
                      ulFileInformationClass));

try_exit:

        NOTHING;
    }

    return ntStatus;
}

NTSTATUS
AFSProcessShareQueryInfo( IN IRP *Irp,
                          IN AFSFcb *Fcb,
                          IN AFSCcb *Ccb)
{

    UNREFERENCED_PARAMETER(Fcb);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    FILE_INFORMATION_CLASS ulFileInformationClass;
    void *pPipeInfo = NULL;

    __Enter
    {

        ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;

        AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessShareQueryInfo On pipe %wZ Class %08lX\n",
                      &Ccb->DirectoryCB->NameInformation.FileName,
                      ulFileInformationClass));

        pPipeInfo = AFSLockSystemBuffer( Irp,
                                         pIrpSp->Parameters.QueryFile.Length);

        if( pPipeInfo == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSProcessShareQueryInfo Failed to lock buffer on pipe %wZ\n",
                          &Ccb->DirectoryCB->NameInformation.FileName));

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        //
        // Send the request to the service
        //

        ntStatus = AFSNotifyQueryPipeInfo( Ccb,
                                           (ULONG)ulFileInformationClass,
                                           pIrpSp->Parameters.QueryFile.Length,
                                           pPipeInfo,
                                           (ULONG *)&Irp->IoStatus.Information);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSProcessShareQueryInfo Failed to send request to service on pipe %wZ Status %08lX\n",
                          &Ccb->DirectoryCB->NameInformation.FileName,
                          ntStatus));

            try_return( ntStatus);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_PIPE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessShareQueryInfo Completed request on pipe %wZ Class %08lX\n",
                      &Ccb->DirectoryCB->NameInformation.FileName,
                      ulFileInformationClass));

try_exit:

        NOTHING;
    }

    return ntStatus;
}

NTSTATUS
AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
                           IN AFSFcb *Fcb,
                           IN AFSCcb *Ccb,
                           IN OUT LONG *Length)
{

    UNREFERENCED_PARAMETER(Fcb);
    UNREFERENCED_PARAMETER(Ccb);
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    FILE_INFORMATION_CLASS ulFileInformationClass;

    __Enter
    {

        ulFileInformationClass = pIrpSp->Parameters.QueryFile.FileInformationClass;

        switch( ulFileInformationClass)
        {

            case FileBasicInformation:
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSProcessPIOCtlQueryInfo (FileBasicInformation)\n"));

                if ( *Length >= sizeof( FILE_BASIC_INFORMATION))
                {
                    PFILE_BASIC_INFORMATION pBasic = (PFILE_BASIC_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

                    pBasic->CreationTime.QuadPart = 0;
                    pBasic->LastAccessTime.QuadPart = 0;
                    pBasic->ChangeTime.QuadPart = 0;
                    pBasic->LastWriteTime.QuadPart = 0;
                    pBasic->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;

                    *Length -= sizeof( FILE_BASIC_INFORMATION);
                }
                else
                {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                }

                break;
            }

            case FileStandardInformation:
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSProcessPIOCtlQueryInfo (FileStandardInformation)\n"));

                if ( *Length >= sizeof( FILE_STANDARD_INFORMATION))
                {
                    PFILE_STANDARD_INFORMATION pStandard = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

                    pStandard->NumberOfLinks = 1;
                    pStandard->DeletePending = 0;
                    pStandard->AllocationSize.QuadPart = 0;
                    pStandard->EndOfFile.QuadPart = 0;
                    pStandard->Directory = 0;

                    *Length -= sizeof( FILE_STANDARD_INFORMATION);
                }
                else
                {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                }

                break;
            }

            case FileNormalizedNameInformation:
            case FileNameInformation:
            {

                ULONG ulCopyLength = 0;
                AFSFcb *pFcb = NULL;
                AFSCcb *pCcb = NULL;
                USHORT usFullNameLength = 0;
                PFILE_NAME_INFORMATION pNameInfo = (PFILE_NAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
                UNICODE_STRING uniName;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSProcessPIOCtlQueryInfo (FileNameInformation)\n"));

                pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;
                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                if( *Length < FIELD_OFFSET( FILE_NAME_INFORMATION, FileName))
                {
                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                    break;
                }

                RtlZeroMemory( pNameInfo,
                               *Length);

                usFullNameLength = sizeof( WCHAR) +
                                            AFSServerName.Length +
                                            pCcb->FullFileName.Length;

                if( *Length >= (LONG)(FIELD_OFFSET( FILE_NAME_INFORMATION, FileName) + (LONG)usFullNameLength))
                {
                    ulCopyLength = (LONG)usFullNameLength;
                }
                else
                {
                    ulCopyLength = *Length - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);
                    ntStatus = STATUS_BUFFER_OVERFLOW;
                }

                pNameInfo->FileNameLength = (ULONG)usFullNameLength;

                *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName);

                if( ulCopyLength > 0)
                {

                    pNameInfo->FileName[ 0] = L'\\';
                    ulCopyLength -= sizeof( WCHAR);

                    *Length -= sizeof( WCHAR);

                    if( ulCopyLength >= AFSServerName.Length)
                    {

                        RtlCopyMemory( &pNameInfo->FileName[ 1],
                                       AFSServerName.Buffer,
                                       AFSServerName.Length);

                        ulCopyLength -= AFSServerName.Length;
                        *Length -= AFSServerName.Length;

                        if( ulCopyLength >= pCcb->FullFileName.Length)
                        {

                            RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
                                           pCcb->FullFileName.Buffer,
                                           pCcb->FullFileName.Length);

                            ulCopyLength -= pCcb->FullFileName.Length;
                            *Length -= pCcb->FullFileName.Length;

                            uniName.Length = (USHORT)pNameInfo->FileNameLength;
                            uniName.MaximumLength = uniName.Length;
                            uniName.Buffer = pNameInfo->FileName;
                        }
                        else
                        {

                            RtlCopyMemory( &pNameInfo->FileName[ 1 + (AFSServerName.Length/sizeof( WCHAR))],
                                           pCcb->FullFileName.Buffer,
                                           ulCopyLength);

                            *Length -= ulCopyLength;

                            uniName.Length = (USHORT)(sizeof( WCHAR) + AFSServerName.Length + ulCopyLength);
                            uniName.MaximumLength = uniName.Length;
                            uniName.Buffer = pNameInfo->FileName;
                        }

                        AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSProcessPIOCtlQueryInfo (FileNameInformation) Returning %wZ\n",
                                      &uniName));
                    }
                }

                break;
            }

            case FileInternalInformation:
            {

                PFILE_INTERNAL_INFORMATION pInternalInfo = (PFILE_INTERNAL_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSProcessPIOCtlQueryInfo (FileInternalInformation)\n"));

                if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
                {

                    pInternalInfo->IndexNumber.HighPart = 0;

                    pInternalInfo->IndexNumber.LowPart = 0;

                    *Length -= sizeof( FILE_INTERNAL_INFORMATION);
                }
                else
                {

                    ntStatus = STATUS_BUFFER_TOO_SMALL;
                }

                break;
            }

            case FileAllInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileAllInformation) Not Implemented\n"));

                break;
            }

            case FileEaInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileEaInformation) Not Implemented\n"));

                break;
            }

            case FilePositionInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FilePositionInformation) Not Implemented\n"));

                break;
            }

            case FileAlternateNameInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileAlternateNameInformation) Not Implemented\n"));

                break;
            }

            case FileNetworkOpenInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileNetworkOpenInformation) Not Implemented\n"));

                break;
            }

            case FileStreamInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileStreamInformation) Not Implemented\n"));

                break;
            }

            case FileAttributeTagInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileAttributeTagInformation) Not Implemented\n"));

                break;
            }

            case FileRemoteProtocolInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileRemoteProtocolInformation) Not Implemented\n"));

                break;
            }

            case FileNetworkPhysicalNameInformation:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo (FileNetworkPhysicalNameInformation) Not Implemented\n"));

                break;
            }

            default:
            {
                ntStatus = STATUS_INVALID_PARAMETER;

                AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSProcessPIOCtlQueryInfo Not handling request %08lX\n",
                              ulFileInformationClass));

                break;
            }
        }
    }

    AFSDbgTrace(( AFS_SUBSYSTEM_PIOCTL_PROCESSING,
                  AFS_TRACE_LEVEL_VERBOSE,
                  "AFSProcessPIOCtlQueryInfo ntStatus %08lX\n",
                  ntStatus));

    return ntStatus;
}

