Windows: Perform rename to self check earlier
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSFileInfo.cpp
index 4abd76e..86751d0 100644 (file)
@@ -139,6 +139,15 @@ AFSQueryFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
             try_return( ntStatus);
         }
 
+        else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryFileInfo request against Invalid Fcb\n");
+
+            try_return( ntStatus = STATUS_ACCESS_DENIED);
+        }
+
         //
         // Process the request
         //
@@ -556,6 +565,16 @@ AFSSetFileInfo( IN PDEVICE_OBJECT LibDeviceObject,
                           "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)
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSSetFileInfo request against Invalid Fcb\n");
+
             try_return( ntStatus = STATUS_ACCESS_DENIED);
         }
 
@@ -1603,7 +1622,7 @@ AFSQueryAttribTagInfo( IN PIRP Irp,
 
         if( BooleanFlagOn( DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
         {
-            Buffer->ReparseTag = IO_REPARSE_TAG_OPENAFS_DFS;
+            Buffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;
         }
 
         *Length -= sizeof( FILE_ATTRIBUTE_TAG_INFORMATION);
@@ -1976,7 +1995,7 @@ AFSSetDispositionInfo( IN PIRP Irp,
                     try_return( ntStatus = STATUS_DIRECTORY_NOT_EMPTY);
                 }
             }
-            else
+            else if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
             {
 
                 //
@@ -2064,6 +2083,7 @@ AFSSetRenameInfo( IN PIRP Irp)
     BOOLEAN bReleaseTargetDirLock = FALSE;
     BOOLEAN bReleaseSourceDirLock = FALSE;
     PERESOURCE  pSourceDirLock = NULL;
+    LONG lCount;
 
     __Enter
     {
@@ -2074,6 +2094,7 @@ AFSSetRenameInfo( IN PIRP Irp)
         pSrcCcb = (AFSCcb *)pSrcFileObj->FsContext2;
 
         pSrcObject = pSrcFcb->ObjectInformation;
+        pSrcParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
 
         //
         // Perform some basic checks to ensure FS integrity
@@ -2111,20 +2132,15 @@ AFSSetRenameInfo( IN PIRP Irp)
                 try_return( ntStatus = STATUS_ACCESS_DENIED);
             }
         }
-        else
-        {
 
-            if( pSrcFcb->OpenHandleCount > 1)
-            {
+        //
+        // Extract off the final component name from the Fcb
+        //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Attempt to rename directory with open references %wZ\n",
-                              &pSrcCcb->DirectoryCB->NameInformation.FileName);
+        uniSourceName.Length = (USHORT)pSrcCcb->DirectoryCB->NameInformation.FileName.Length;
+        uniSourceName.MaximumLength = uniSourceName.Length;
 
-                try_return( ntStatus = STATUS_ACCESS_DENIED);
-            }
-        }
+        uniSourceName.Buffer = pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer;
 
         //
         // Resolve the target fileobject
@@ -2140,7 +2156,7 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             pRenameInfo = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
 
-            pTargetParentObject = pSrcFcb->ObjectInformation->ParentObjectInformation;
+            pTargetParentObject = pSrcParentObject;
 
             pTargetDcb = pTargetParentObject->Fcb;
 
@@ -2169,6 +2185,31 @@ AFSSetRenameInfo( IN PIRP Irp)
         }
 
         //
+        // 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
         //
 
@@ -2191,7 +2232,7 @@ AFSSetRenameInfo( IN PIRP Irp)
 
         bReleaseTargetDirLock = TRUE;
 
-        if( pTargetParentObject != pSrcFcb->ObjectInformation->ParentObjectInformation)
+        if( pTargetParentObject != pSrcParentObject)
         {
             AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                             TRUE);
@@ -2241,7 +2282,7 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
 
-            InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
+            lCount = InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
 
             if( !bReplaceIfExists)
             {
@@ -2280,40 +2321,6 @@ AFSSetRenameInfo( IN PIRP Irp)
         }
 
         //
-        // 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;
-
-        //
-        // 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 == pSrcFcb->ObjectInformation->ParentObjectInformation)
-        {
-
-            bCommonParent = TRUE;
-
-            if( FsRtlAreNamesEqual( &uniTargetName,
-                                    &uniSourceName,
-                                    FALSE,
-                                    NULL))
-            {
-                try_return( ntStatus = STATUS_SUCCESS);
-            }
-        }
-        else
-        {
-
-            bCommonParent = FALSE;
-        }
-
-        //
         // 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
@@ -2453,8 +2460,17 @@ AFSSetRenameInfo( IN PIRP Irp)
             else
             {
 
-                AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
-                                    &pSrcObject->TreeEntry);
+                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);
@@ -2520,13 +2536,13 @@ AFSSetRenameInfo( IN PIRP Irp)
         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation != pTargetParentObject)
         {
 
-            InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
+            lCount = InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
 
-            InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
+            lCount = InterlockedDecrement( &pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
 
-            InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
+            lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenHandleCount);
 
-            InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
+            lCount = InterlockedIncrement( &pTargetParentObject->Specific.Directory.ChildOpenReferenceCount);
 
             pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation = pTargetParentObject;
 
@@ -2596,9 +2612,9 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
 
-            InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
+            lCount = InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
 
-            if( pTargetDirEntry->OpenReferenceCount == 0)
+            if( lCount == 0)
             {
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -2631,7 +2647,7 @@ try_exit:
         if( pTargetDirEntry != NULL)
         {
 
-            InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
+            lCount = InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
         }
 
         if( bReleaseTargetDirLock)