Windows: AFSSetRenameInfo Notify correct object of change
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFileInfo.cpp
index 3353256..26107b4 100644 (file)
@@ -55,16 +55,15 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                   IN PIRP Irp)
 {
 
+    UNREFERENCED_PARAMETER(LibDeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
-    ULONG ulRequestType = 0;
     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
     AFSFcb *pFcb = NULL;
     AFSCcb *pCcb = NULL;
-    PFILE_OBJECT pFileObject;
     BOOLEAN bReleaseMain = FALSE;
-    LONG lLength;
+    LONG lLength = 0;
     FILE_INFORMATION_CLASS stFileInformationClass;
+    GUID stAuthGroup;
     PVOID pBuffer;
 
     __try
@@ -83,7 +82,7 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryFileInfo Attempted access (%08lX) when pFcb == NULL\n",
+                          "AFSQueryFileInfo Attempted access (%p) when pFcb == NULL\n",
                           Irp);
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
@@ -93,13 +92,38 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
         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);
+
+            if ( NT_SUCCESS( ntStatus))
+            {
+
+                ClearFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+            }
+            else
+            {
+
+                ntStatus = STATUS_SUCCESS;
+            }
+        }
+
         //
         // Grab the main shared right off the bat
         //
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSQueryFileInfo Acquiring Fcb lock %08lX SHARED %08lX\n",
+                      "AFSQueryFileInfo Acquiring Fcb lock %p SHARED %08lX\n",
                       &pFcb->NPFcb->Resource,
                       PsGetCurrentThread());
 
@@ -483,12 +507,11 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                 IN PIRP Irp)
 {
 
+    UNREFERENCED_PARAMETER(LibDeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
     AFSFcb *pFcb = NULL;
     AFSCcb *pCcb = NULL;
-    BOOLEAN bCompleteRequest = TRUE;
     FILE_INFORMATION_CLASS FileInformationClass;
     BOOLEAN bCanQueueRequest = FALSE;
     PFILE_OBJECT pFileObject = NULL;
@@ -509,7 +532,7 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSSetFileInfo Attempted access (%08lX) when pFcb == NULL\n",
+                          "AFSSetFileInfo Attempted access (%p) when pFcb == NULL\n",
                           Irp);
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
@@ -524,7 +547,7 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSSetFileInfo Acquiring Fcb lock %08lX EXCL %08lX\n",
+                      "AFSSetFileInfo Acquiring Fcb lock %p EXCL %08lX\n",
                       &pFcb->NPFcb->Resource,
                       PsGetCurrentThread());
 
@@ -650,7 +673,7 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
             case FileLinkInformation:
             {
 
-                ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+                ntStatus = AFSSetFileLinkInfo( Irp);
 
                 break;
             }
@@ -1001,6 +1024,7 @@ AFSQueryInternalInfo( IN PIRP Irp,
                       IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
     NTSTATUS ntStatus = STATUS_SUCCESS;
 
     if( *Length >= sizeof( FILE_INTERNAL_INFORMATION))
@@ -1028,6 +1052,8 @@ AFSQueryEaInfo( IN PIRP Irp,
                 IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
+    UNREFERENCED_PARAMETER(DirectoryCB);
     NTSTATUS ntStatus = STATUS_SUCCESS;
 
     RtlZeroMemory( Buffer,
@@ -1056,6 +1082,7 @@ AFSQueryPositionInfo( IN PIRP Irp,
                       IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
 
@@ -1085,6 +1112,8 @@ AFSQueryAccess( IN PIRP Irp,
                 IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
 
     if( *Length >= sizeof( FILE_ACCESS_INFORMATION))
@@ -1113,6 +1142,8 @@ AFSQueryMode( IN PIRP Irp,
               IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
 
     if( *Length >= sizeof( FILE_MODE_INFORMATION))
@@ -1141,6 +1172,8 @@ AFSQueryAlignment( IN PIRP Irp,
                    IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
 
     if( *Length >= sizeof( FILE_ALIGNMENT_INFORMATION))
@@ -1169,6 +1202,7 @@ AFSQueryNameInfo( IN PIRP Irp,
                   IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(DirectoryCB);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     ULONG ulCopyLength = 0;
     ULONG cchCopied = 0;
@@ -1311,6 +1345,7 @@ AFSQueryShortNameInfo( IN PIRP Irp,
                        IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
     ULONG ulCopyLength = 0;
 
@@ -1524,9 +1559,9 @@ AFSQueryStreamInfo( IN PIRP Irp,
                     IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
     ULONG ulCopyLength = 0;
-    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
 
     if( *Length >= FIELD_OFFSET( FILE_STREAM_INFORMATION, StreamName))
     {
@@ -1595,7 +1630,6 @@ AFSQueryAttribTagInfo( IN PIRP Irp,
 {
 
     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
-    ULONG ulCopyLength = 0;
     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     AFSFcb *pFcb = NULL;
     AFSCcb *pCcb = NULL;
@@ -1709,9 +1743,9 @@ AFSQueryRemoteProtocolInfo( IN PIRP Irp,
                             IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(Irp);
+    UNREFERENCED_PARAMETER(DirectoryCB);
     NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
-    ULONG ulCopyLength = 0;
-    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
 
     if( *Length >= sizeof( FILE_REMOTE_PROTOCOL_INFORMATION))
     {
@@ -1746,6 +1780,7 @@ AFSQueryPhysicalNameInfo( IN PIRP Irp,
                           IN OUT PLONG Length)
 {
 
+    UNREFERENCED_PARAMETER(DirectoryCB);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     ULONG ulCopyLength = 0;
     ULONG cchCopied = 0;
@@ -2038,6 +2073,13 @@ AFSSetDispositionInfo( IN PIRP Irp,
             {
 
                 //
+                // Reduce the Link count in the object information block
+                // to correspond with the deletion of the directory entry.
+                //
+
+                pFcb->ObjectInformation->Links--;
+
+                //
                 // Check if this is a directory that there are not currently other opens
                 //
 
@@ -2074,52 +2116,76 @@ AFSSetDispositionInfo( IN PIRP Irp,
             }
             else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
             {
+                BOOLEAN bMmFlushed;
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSSetDispositionInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
+                                TRUE);
 
                 //
                 // Attempt to flush any outstanding data
                 //
 
-                if( !MmFlushImageSection( &pFcb->NPFcb->SectionObjectPointers,
-                                          MmFlushForDelete))
+                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.
+                    //
+
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_ERROR,
-                                  "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
+                                  DirectoryCB,
                                   &DirectoryCB->NameInformation.FileName);
 
-                    try_return( ntStatus = STATUS_CANNOT_DELETE);
-                }
+                    SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
 
-                //
-                // 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.
-                //
+                    //
+                    // Purge the cache as well
+                    //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSSetDispositionInfo Setting PENDING_DELETE on DirEntry %p Name %wZ\n",
-                              DirectoryCB,
-                              &DirectoryCB->NameInformation.FileName);
+                    if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
+                    {
 
-                SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
+                        if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
+                                                   NULL,
+                                                   0,
+                                                   TRUE))
+                        {
 
-                //
-                // Purge the cache as well
-                //
+                            SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
+                        }
+                    }
+                }
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSSetDispositionInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread());
+
+                AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
 
-                if( pFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
+                if ( !bMmFlushed)
                 {
 
-                    if ( !CcPurgeCacheSection( &pFcb->NPFcb->SectionObjectPointers,
-                                               NULL,
-                                               0,
-                                               TRUE))
-                    {
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_ERROR,
+                                  "AFSSetDispositionInfo Failed to flush image section for delete Entry %wZ\n",
+                                  &DirectoryCB->NameInformation.FileName);
 
-                        SetFlag( pFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
-                    }
+                    try_return( ntStatus = STATUS_CANNOT_DELETE);
                 }
             }
         }
@@ -2144,39 +2210,34 @@ try_exit:
 }
 
 NTSTATUS
-AFSSetRenameInfo( IN PIRP Irp)
+AFSSetFileLinkInfo( IN PIRP Irp)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
-    IO_STATUS_BLOCK stIoSb = {0,0};
-    AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL, *pTargetFcb = NULL;
-    AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
-    PFILE_OBJECT pSrcFileObj = pIrpSp->FileObject;
+    PFILE_LINK_INFORMATION pFileLinkInfo = NULL;
+    PFILE_OBJECT pSrcFileObj = NULL;
     PFILE_OBJECT pTargetFileObj = pIrpSp->Parameters.SetFile.FileObject;
-    PFILE_RENAME_INFORMATION pRenameInfo = NULL;
-    UNICODE_STRING uniTargetName, uniSourceName;
-    BOOLEAN bReplaceIfExists = FALSE;
-    UNICODE_STRING uniShortName;
-    AFSDirectoryCB *pTargetDirEntry = NULL;
-    ULONG ulTargetCRC = 0;
-    BOOLEAN bTargetEntryExists = FALSE;
-    AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
+    AFSFcb *pSrcFcb = NULL, *pTargetDcb = NULL;
+    AFSCcb *pSrcCcb = NULL, *pTargetDirCcb = NULL;
+    AFSObjectInfoCB *pSrcObject = NULL;
     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
-    AFSFileID stNewFid, stTmpTargetFid;
-    ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
-    UNICODE_STRING uniFullTargetPath;
+    UNICODE_STRING uniSourceName, uniTargetName;
+    UNICODE_STRING uniFullTargetName, uniTargetParentName;
     BOOLEAN bCommonParent = FALSE;
-    BOOLEAN bReleaseTargetDirLock = FALSE;
-    BOOLEAN bReleaseSourceDirLock = FALSE;
-    PERESOURCE  pSourceDirLock = NULL;
+    AFSDirectoryCB *pTargetDirEntry = NULL;
+    AFSDirectoryCB *pNewTargetDirEntry = NULL;
+    ULONG ulTargetCRC;
+    BOOLEAN bTargetEntryExists = FALSE;
     LONG lCount;
+    BOOLEAN bReleaseTargetDirLock = FALSE;
+    ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
 
     __Enter
     {
 
-        bReplaceIfExists = pIrpSp->Parameters.SetFile.ReplaceIfExists;
+        pSrcFileObj = pIrpSp->FileObject;
 
         pSrcFcb = (AFSFcb *)pSrcFileObj->FsContext;
         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
@@ -2184,72 +2245,88 @@ AFSSetRenameInfo( IN PIRP Irp)
         pSrcObject = pSrcFcb->ObjectInformation;
         pSrcParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
 
+        pFileLinkInfo = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+
         //
         // Perform some basic checks to ensure FS integrity
         //
 
-        if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
+        if( pSrcFcb->Header.NodeTypeCode != AFS_FILE_FCB)
         {
 
-            //
-            // Can't rename the root directory
-            //
-
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSSetRenameInfo Attempt to rename root entry\n");
+                          "AFSSetFileLinkInfo Attempt to non-file (INVALID_PARAMETER)\n");
 
             try_return( ntStatus = STATUS_INVALID_PARAMETER);
         }
 
-        if( pSrcFcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
+        if( pTargetFileObj == NULL)
         {
 
-            //
-            // If there are any open children then fail the rename
-            //
-
-            if( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+            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.
+                //
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Attempt to rename directory with open children %wZ\n",
+                              "AFSSetFileLinkInfo Attempt to link %wZ to alternate directory by handle INVALID_PARAMETER\n",
                               &pSrcCcb->DirectoryCB->NameInformation.FileName);
 
-                try_return( ntStatus = STATUS_ACCESS_DENIED);
+                try_return( ntStatus = STATUS_INVALID_PARAMETER);
             }
-        }
+            else
+            {
 
-        //
-        // Extract off the final component name from the Fcb
-        //
+                uniFullTargetName.Length = (USHORT)pFileLinkInfo->FileNameLength;
 
-        uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
-        uniSourceName.MaximumLength = uniSourceName.Length;
+                uniFullTargetName.Buffer = (PWSTR)&pFileLinkInfo->FileName;
 
-        uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
+                AFSRetrieveFinalComponent( &uniFullTargetName,
+                                           &uniTargetName);
 
-        //
-        // Resolve the target fileobject
-        //
+                AFSRetrieveParentPath( &uniFullTargetName,
+                                       &uniTargetParentName);
 
-        if( pTargetFileObj == NULL)
-        {
+                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
-            //
+                    //
+                    // 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
+                    //
 
-            pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
+                    pTargetParentObject = pSrcParentObject;
+                }
+                else
+                {
+                    //
+                    // uniTargetParentName contains the directory the renamed object
+                    // will be moved to.  Must obtain the TargetParentObject.
+                    //
 
-            pTargetParentObject = pSrcParentObject;
+                    AFSDbgLogMsg( 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);
 
-            pTargetDcb = pTargetParentObject->Fcb;
+                    try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
+                }
+            }
 
-            uniTargetName.Length = (USHORT)pRenameInfo->FileNameLength;
-            uniTargetName.Buffer = (PWSTR)&pRenameInfo->FileName;
+            pTargetDcb = pTargetParentObject->Fcb;
         }
         else
         {
@@ -2273,7 +2350,7 @@ AFSSetRenameInfo( IN PIRP Irp)
         }
 
         //
-        // The quick check to see if they are not really performing a rename
+        // The quick check to see if they are self linking.
         // Do the names match? Only do this where the parent directories are
         // the same
         //
@@ -2294,22 +2371,20 @@ AFSSetRenameInfo( IN PIRP Irp)
         else
         {
 
-            bCommonParent = FALSE;
-        }
-
-        //
-        // We do not allow cross-volume renames to occur
-        //
+            //
+            // We do not allow cross-volume hard links
+            //
 
-        if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
-        {
+            if( pTargetParentObject->VolumeCB != pSrcObject->VolumeCB)
+            {
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                          AFS_TRACE_LEVEL_ERROR,
-                          "AFSSetRenameInfo Attempt to rename directory to different volume %wZ\n",
-                          &pSrcCcb->DirectoryCB->NameInformation.FileName);
+                AFSDbgLogMsg( 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);
+                try_return( ntStatus = STATUS_NOT_SAME_DEVICE);
+            }
         }
 
         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
@@ -2320,16 +2395,6 @@ AFSSetRenameInfo( IN PIRP Irp)
 
         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);
@@ -2351,8 +2416,8 @@ AFSSetRenameInfo( IN PIRP Irp)
 
         if ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
              pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
-                                                               NULL,
-                                                               NULL))
+                                                                NULL,
+                                                                NULL))
         {
             //
             // Try the short name
@@ -2371,26 +2436,36 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
 
-            lCount = InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
+            lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
 
-            if( !bReplaceIfExists)
+            AFSDbgLogMsg( 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)
             {
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
+                              "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);
             }
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSSetRenameInfo Target %wZ exists DE %p Count %08lX, performing delete of target\n",
+                          "AFSSetFileLinkInfo Target %wZ exists DE %p Count %d, performing delete of target\n",
                           &pTargetDirEntry->NameInformation.FileName,
                           pTargetDirEntry,
-                          pTargetDirEntry->OpenReferenceCount);
+                          lCount);
 
             //
             // Pull the directory entry from the parent
@@ -2406,46 +2481,30 @@ AFSSetRenameInfo( IN PIRP Irp)
         {
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSSetRenameInfo Target does NOT exist, normal rename\n");
+                          "AFSSetFileLinkInfo Target does NOT exist, normal linking\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( pSrcFcb->ObjectInformation->ParentObjectInformation,
-                                    pSrcCcb->DirectoryCB,
-                                    !bCommonParent);
-
-        //
         // OK, this is a simple rename. Issue the rename
         // request to the service.
         //
 
-        ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
-                                    &pSrcCcb->AuthGroup,
-                                    pSrcFcb->ObjectInformation->ParentObjectInformation,
-                                    pTargetDcb->ObjectInformation,
-                                    pSrcCcb->DirectoryCB,
-                                    &uniTargetName,
-                                    &stNewFid);
-
-        if( !NT_SUCCESS( ntStatus))
+        ntStatus = AFSNotifyHardLink( pSrcFcb->ObjectInformation,
+                                      &pSrcCcb->AuthGroup,
+                                      pSrcFcb->ObjectInformation->ParentObjectInformation,
+                                      pTargetDcb->ObjectInformation,
+                                      pSrcCcb->DirectoryCB,
+                                      &uniTargetName,
+                                      pFileLinkInfo->ReplaceIfExists,
+                                      &pNewTargetDirEntry);
+
+        if( ntStatus != STATUS_REPARSE &&
+            !NT_SUCCESS( ntStatus))
         {
 
-            //
-            // Attempt to re-insert the directory entry
-            //
-
-            AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
-                                    pSrcCcb->DirectoryCB,
-                                    !bCommonParent);
-
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSSetRenameInfo Failed rename of %wZ to target %wZ Status %08lX\n",
+                          "AFSSetFileLinkInfo Failed link of %wZ to target %wZ Status %08lX\n",
                           &pSrcCcb->DirectoryCB->NameInformation.FileName,
                           &uniTargetName,
                           ntStatus);
@@ -2453,62 +2512,515 @@ AFSSetRenameInfo( IN PIRP Irp)
             try_return( ntStatus);
         }
 
-        //
-        // Set the notification up for the source file
-        //
-
-        if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
-            !bTargetEntryExists)
+        if ( ntStatus != STATUS_REPARSE)
         {
 
-            ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
+            AFSInsertDirectoryNode( pTargetDcb->ObjectInformation,
+                                    pNewTargetDirEntry,
+                                    TRUE);
         }
-        else
-        {
 
-            ulNotificationAction = FILE_ACTION_REMOVED;
-        }
+        //
+        // Send notification for the target link file
+        //
 
-        if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
+        if( bTargetEntryExists || pNewTargetDirEntry)
         {
 
-            ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
+            ulNotificationAction = FILE_ACTION_MODIFIED;
         }
         else
         {
 
-            ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
+            ulNotificationAction = FILE_ACTION_ADDED;
         }
 
-        AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
+        AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
                                         pSrcCcb,
                                         (ULONG)ulNotifyFilter,
                                         (ULONG)ulNotificationAction);
 
-        //
-        // Update the name in the dir entry.
-        //
-
-        ntStatus = AFSUpdateDirEntryName( pSrcCcb->DirectoryCB,
-                                          &uniTargetName);
+      try_exit:
 
         if( !NT_SUCCESS( ntStatus))
         {
 
+            if( bTargetEntryExists)
+            {
+
+                AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
+                                        pTargetDirEntry,
+                                        FALSE);
+            }
+        }
+
+        if( pTargetDirEntry != NULL)
+        {
+
             //
-            // Attempt to re-insert the directory entry
+            // Release DirOpenReferenceCount obtained above
             //
 
-            AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
-                                    pSrcCcb->DirectoryCB,
-                                    !bCommonParent);
+            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
 
-            AFSDbgLogMsg( 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);
+            AFSDbgLogMsg( 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);
+
+            AFSDbgLogMsg( 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);
+        }
+    }
+
+    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;
+        pSrcParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
+
+        //
+        // Perform some basic checks to ensure FS integrity
+        //
+
+        if( pSrcFcb->Header.NodeTypeCode == AFS_ROOT_FCB)
+        {
+
+            //
+            // Can't rename the root directory
+            //
+
+            AFSDbgLogMsg( 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( pSrcFcb->ObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
+            {
+
+                AFSDbgLogMsg( 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)
+            {
+
+                AFSDbgLogMsg( 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.
+                    //
+
+                    AFSDbgLogMsg( 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)
+        {
+
+            AFSDbgLogMsg( 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 ( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
+             pTargetDirEntry == NULL && RtlIsNameLegalDOS8Dot3( &uniTargetName,
+                                                               NULL,
+                                                               NULL))
+        {
+            //
+            // Try the short name
+            //
+            AFSLocateShortNameDirEntry( pTargetParentObject->Specific.Directory.ShortNameTree,
+                                        ulTargetCRC,
+                                        &pTargetDirEntry);
+        }
+
+        //
+        // Increment our ref count on the dir entry
+        //
+
+        if( pTargetDirEntry != NULL)
+        {
+
+            ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
+
+            lCount = InterlockedIncrement( &pTargetDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( 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);
+
+            if( !bReplaceIfExists)
+            {
+
+                AFSDbgLogMsg( 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);
+            }
+
+            AFSDbgLogMsg( 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
+        {
+            AFSDbgLogMsg( 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( pSrcFcb->ObjectInformation->ParentObjectInformation,
+                                    pSrcCcb->DirectoryCB,
+                                    !bCommonParent);
+
+        //
+        // OK, this is a simple rename. Issue the rename
+        // request to the service.
+        //
+
+        ntStatus = AFSNotifyRename( pSrcFcb->ObjectInformation,
+                                    &pSrcCcb->AuthGroup,
+                                    pSrcFcb->ObjectInformation->ParentObjectInformation,
+                                    pTargetDcb->ObjectInformation,
+                                    pSrcCcb->DirectoryCB,
+                                    &uniTargetName,
+                                    &stNewFid);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            //
+            // Attempt to re-insert the directory entry
+            //
+
+            AFSInsertDirectoryNode( pSrcFcb->ObjectInformation->ParentObjectInformation,
+                                    pSrcCcb->DirectoryCB,
+                                    !bCommonParent);
+
+            AFSDbgLogMsg( 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( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
+            !bTargetEntryExists)
+        {
+
+            ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
+        }
+        else
+        {
+
+            ulNotificationAction = FILE_ACTION_REMOVED;
+        }
+
+        if( pSrcCcb->DirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
+        {
+
+            ulNotifyFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
+        }
+        else
+        {
+
+            ulNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
+        }
+
+        AFSFsRtlNotifyFullReportChange( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
+                                        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( pSrcFcb->ObjectInformation->ParentObjectInformation,
+                                    pSrcCcb->DirectoryCB,
+                                    !bCommonParent);
+
+            AFSDbgLogMsg( 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);
         }
@@ -2634,6 +3146,24 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
 
+            lCount = AFSObjectInfoIncrement( pTargetParentObject,
+                                             AFS_OBJECT_REFERENCE_CHILD);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSSetRenameInfo Increment count on parent object %p Cnt %d\n",
+                          pTargetParentObject,
+                          lCount);
+
+            lCount = AFSObjectInfoDecrement( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
+                                             AFS_OBJECT_REFERENCE_CHILD);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSSetRenameInfo Decrement count on parent object %p Cnt %d\n",
+                          pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation,
+                          lCount);
+
             pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
 
             ulNotificationAction = FILE_ACTION_ADDED;
@@ -2648,7 +3178,7 @@ AFSSetRenameInfo( IN PIRP Irp)
         // Now update the notification for the target file
         //
 
-        AFSFsRtlNotifyFullReportChange( pTargetParentObject->ParentObjectInformation,
+        AFSFsRtlNotifyFullReportChange( pTargetParentObject,
                                         pSrcCcb,
                                         (ULONG)ulNotifyFilter,
                                         (ULONG)ulNotificationAction);
@@ -2675,14 +3205,89 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             if( pTargetDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
                 pTargetDirEntry->ObjectInformation->Fcb != NULL &&
-                pTargetDirEntry->OpenReferenceCount > 1)
+                pTargetDirEntry->DirOpenReferenceCount > 1)
             {
 
                 pTargetFcb = pTargetDirEntry->ObjectInformation->Fcb;
+            }
+
+            ASSERT( pTargetDirEntry->DirOpenReferenceCount > 0);
+
+            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount); // The count we added above
+
+            AFSDbgLogMsg( 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)
+            {
+
+                AFSDbgLogMsg( 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.
+                //
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSSetRenameInfo Acquiring Fcb lock %p EXCL %08lX\n",
+                              &pTargetFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
 
                 AFSAcquireExcl( &pTargetFcb->NPFcb->Resource,
                                 TRUE);
 
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSSetRenameInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pTargetFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread());
+
+                AFSAcquireExcl( &pTargetFcb->NPFcb->SectionObjectResource,
+                                TRUE);
+
                 //
                 // Close the section in the event it was mapped
                 //
@@ -2694,35 +3299,29 @@ AFSSetRenameInfo( IN PIRP Irp)
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                   AFS_TRACE_LEVEL_ERROR,
                                   "AFSSetRenameInfo Failed to delete section for target file %wZ\n",
-                                  &pTargetDirEntry->NameInformation.FileName);
+                                  &uniTargetName);
                 }
 
-                AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
-            }
-
-            ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
-
-            lCount = InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSSetRenameInfo Releasing Fcb SectionObject lock %p EXCL %08lX\n",
+                              &pTargetFcb->NPFcb->SectionObjectResource,
+                              PsGetCurrentThread());
 
-            if( lCount == 0)
-            {
+                AFSReleaseResource( &pTargetFcb->NPFcb->SectionObjectResource);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
-                              pTargetDirEntry,
-                              &pTargetDirEntry->NameInformation.FileName);
+                              "AFSSetRenameInfo Releasing Fcb lock %p EXCL %08lX\n",
+                              &pTargetFcb->NPFcb->Resource,
+                              PsGetCurrentThread());
 
-                AFSDeleteDirEntry( pTargetParentObject,
-                                   pTargetDirEntry);
+                AFSReleaseResource( &pTargetFcb->NPFcb->Resource);
             }
-
-            pTargetDirEntry = NULL;
         }
 
 try_exit:
 
-
         if( !NT_SUCCESS( ntStatus))
         {
 
@@ -2737,20 +3336,38 @@ try_exit:
         if( pTargetDirEntry != NULL)
         {
 
-            lCount = InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
+            lCount = InterlockedDecrement( &pTargetDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( 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);
+    }
+
     return ntStatus;
 }
 
@@ -2758,6 +3375,7 @@ 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);
@@ -2773,11 +3391,13 @@ 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;
@@ -2807,24 +3427,45 @@ AFSSetAllocationInfo( IN PIRP Irp,
 
     if( pFcb->Header.AllocationSize.QuadPart > pBuffer->AllocationSize.QuadPart)
     {
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSSetAllocationInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                      &pFcb->NPFcb->SectionObjectResource,
+                      PsGetCurrentThread());
+
+        AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
+                        TRUE);
+
+        bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
+                                             &pBuffer->AllocationSize);
+
+        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                      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( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
-                                   &pBuffer->AllocationSize))
+        if ( bUserMapped)
         {
 
             ntStatus = STATUS_USER_MAPPED_FILE ;
         }
         else
         {
+
             //
             // If this is a truncation we need to grab the paging IO resource.
             //
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
+                          "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                           &pFcb->NPFcb->PagingResource,
                           PsGetCurrentThread());
 
@@ -2873,7 +3514,7 @@ AFSSetAllocationInfo( IN PIRP Irp,
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
+                      "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                       &pFcb->NPFcb->PagingResource,
                       PsGetCurrentThread());
 
@@ -2958,6 +3599,7 @@ 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);
@@ -2968,6 +3610,7 @@ AFSSetEndOfFileInfo( IN PIRP Irp,
     BOOLEAN bModified = FALSE;
     BOOLEAN bReleasePaging = FALSE;
     BOOLEAN bTruncated = FALSE;
+    BOOLEAN bUserMapped = FALSE;
     AFSFcb *pFcb = NULL;
     AFSCcb *pCcb = NULL;
 
@@ -2988,9 +3631,28 @@ AFSSetEndOfFileInfo( IN PIRP Irp,
         if( pBuffer->EndOfFile.QuadPart < pFcb->Header.FileSize.QuadPart)
         {
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSSetEndOfFileInfo Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
+                          &pFcb->NPFcb->SectionObjectResource,
+                          PsGetCurrentThread());
+
+            AFSAcquireExcl( &pFcb->NPFcb->SectionObjectResource,
+                            TRUE);
+
+            bUserMapped = !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
+                                                 &pBuffer->EndOfFile);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
+                          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( !MmCanFileBeTruncated( pFileObject->SectionObjectPointer,
-                                       &pBuffer->EndOfFile))
+            if ( bUserMapped)
             {
 
                 ntStatus = STATUS_USER_MAPPED_FILE;
@@ -3004,7 +3666,7 @@ AFSSetEndOfFileInfo( IN PIRP Irp,
                 //
                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
+                              "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                               &pFcb->NPFcb->PagingResource,
                               PsGetCurrentThread());
 
@@ -3053,7 +3715,7 @@ AFSSetEndOfFileInfo( IN PIRP Irp,
             //
             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %08lX EXCL %08lX\n",
+                          "AFSSetAllocationInfo Acquiring Fcb PagingIo lock %p EXCL %08lX\n",
                           &pFcb->NPFcb->PagingResource,
                           PsGetCurrentThread());
 
@@ -3149,9 +3811,9 @@ AFSProcessShareSetInfo( IN IRP *Irp,
                         IN AFSCcb *Ccb)
 {
 
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
-    ULONG ulOutputBufferLen = 0, ulInputBufferLen;
     FILE_INFORMATION_CLASS ulFileInformationClass;
     void *pPipeInfo = NULL;
 
@@ -3220,9 +3882,9 @@ AFSProcessShareQueryInfo( IN IRP *Irp,
                           IN AFSCcb *Ccb)
 {
 
+    UNREFERENCED_PARAMETER(Fcb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
-    ULONG ulOutputBufferLen = 0, ulInputBufferLen;
     FILE_INFORMATION_CLASS ulFileInformationClass;
     void *pPipeInfo = NULL;
 
@@ -3294,6 +3956,8 @@ AFSProcessPIOCtlQueryInfo( IN IRP *Irp,
                            IN OUT LONG *Length)
 {
 
+    UNREFERENCED_PARAMETER(Fcb);
+    UNREFERENCED_PARAMETER(Ccb);
     NTSTATUS ntStatus = STATUS_SUCCESS;
     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
     FILE_INFORMATION_CLASS ulFileInformationClass;