Windows: Directory Entry Processing
authorPeter Scott <pscott@kerneldrivers.com>
Sat, 29 Oct 2011 17:55:46 +0000 (13:55 -0400)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 1 Nov 2011 14:48:38 +0000 (07:48 -0700)
Memory corruption was detected due to improper handling
of directory entries and the short name b-tree during
directory revalidation and tear down.  The problem
resulted in a BSOD most frequently when roaming profiles
were written back to the file server or when multiple
clients were actively modifying the contents of a directory
simultaneously.

This patchset makes a number of changes:

 . rename processing no longer handles collisions locally.
   the file server replaces a target atomicly when there
   is a collision.

 . directory validation is no longer delayed until
   a handle is closed

 . data version numbers are checked for implied
   invalidation

Change-Id: Ib4b281bfb5da4b5a5ce735e85d85c50e15fbcde1
Reviewed-on: http://gerrit.openafs.org/5736
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Rod Widdowson <rdw@steadingsoftware.com>
Reviewed-by: Jeffrey Altman <jaltman@secure-endpoints.com>
Tested-by: Jeffrey Altman <jaltman@secure-endpoints.com>

src/WINNT/afsrdr/kernel/lib/AFSBTreeSupport.cpp
src/WINNT/afsrdr/kernel/lib/AFSCommSupport.cpp
src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp
src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp
src/WINNT/afsrdr/kernel/lib/AFSFileInfo.cpp
src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp
src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp
src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h
src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h

index 5320e7e..0e4331d 100644 (file)
@@ -1083,6 +1083,8 @@ AFSInsertShortNameDirEntry( IN AFSDirectoryCB *RootNode,
             else
             {
 
+                ntStatus = STATUS_UNSUCCESSFUL;
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSInsertShortNameDirEntry Collision with DE %p for shortname %S and %wZ\n",
index c5d380c..df5ce4b 100644 (file)
@@ -263,17 +263,35 @@ AFSEnumerateDirectory( IN GUID *AuthGroup,
                     //
 
                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
+                    uniShortName.MaximumLength = uniShortName.Length;
                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
 
-                    pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
-                                                                                       TRUE);
+                    if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
+                                                 NULL,
+                                                 NULL))
+                    {
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ\n",
-                                  &uniShortName,
-                                  pDirNode,
-                                  &pDirNode->NameInformation.FileName);
+                        pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
+                                                                                           TRUE);
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                                      &uniShortName,
+                                      pDirNode,
+                                      &pDirNode->NameInformation.FileName,
+                                      pCurrentDirEntry->FileId.Cell,
+                                      pCurrentDirEntry->FileId.Volume,
+                                      pCurrentDirEntry->FileId.Vnode,
+                                      pCurrentDirEntry->FileId.Unique);
+                    }
+                    else
+                    {
+                        pDirNode->NameInformation.ShortNameLength = 0;
+
+                        RtlZeroMemory( pDirNode->NameInformation.ShortName,
+                                       (12 * sizeof( WCHAR)));
+                    }
                 }
 
                 //
@@ -302,10 +320,34 @@ AFSEnumerateDirectory( IN GUID *AuthGroup,
                                   pDirNode,
                                   &pDirNode->NameInformation.FileName);
 
-                    AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
-                                                    pDirNode);
+                    if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                                     pDirNode)))
+                    {
+
+                        //
+                        // Delete this dir entry and continue on
+                        //
+
+                        AFSDeleteDirEntry( ObjectInfoCB,
+                                           pDirNode);
+
+                        pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                        if( ulResultLen >= ulEntryLength)
+                        {
+                            ulResultLen -= ulEntryLength;
+                        }
+                        else
+                        {
+                            ulResultLen = 0;
+                        }
+
+                        continue;
+                    }
                 }
 
+                ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
+
                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
                 {
 
@@ -378,18 +420,23 @@ AFSEnumerateDirectory( IN GUID *AuthGroup,
                                       &pDirNode->NameInformation.FileName);
 
                         ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
+
+                        SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
                     }
                     else
                     {
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
-                                      pDirNode,
-                                      &pDirNode->NameInformation.FileName);
+                        if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
+                                                                    pDirNode)))
+                        {
+                            SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
 
-                        AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
-                                                    pDirNode);
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
+                                          pDirNode,
+                                          &pDirNode->NameInformation.FileName);
+                        }
                     }
                 }
 
@@ -907,10 +954,38 @@ AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
                     //
 
                     uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
+                    uniShortName.MaximumLength = uniShortName.Length;
                     uniShortName.Buffer = pDirNode->NameInformation.ShortName;
 
-                    pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
-                                                                                       TRUE);
+                    if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
+                                                 NULL,
+                                                 NULL))
+                    {
+
+                        pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
+                                                                                           TRUE);
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                                      &uniShortName,
+                                      pDirNode,
+                                      &pDirNode->NameInformation.FileName,
+                                      pCurrentDirEntry->FileId.Cell,
+                                      pCurrentDirEntry->FileId.Volume,
+                                      pCurrentDirEntry->FileId.Vnode,
+                                      pCurrentDirEntry->FileId.Unique);
+                    }
+                    else
+                    {
+                        pDirNode->NameInformation.ShortNameLength = 0;
+
+                        RtlZeroMemory( pDirNode->NameInformation.ShortName,
+                                       (12 * sizeof( WCHAR)));
+                    }
+                }
+                else
+                {
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                   AFS_TRACE_LEVEL_VERBOSE,
@@ -943,16 +1018,47 @@ AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
                 else
                 {
 
-                    AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
-                                                    pDirNode);
+                    if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                                     pDirNode)))
+                    {
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSVerifyDirectoryContent Failed to nsert DE %p to case sensitive tree for %wZ\n",
+                                      pDirNode,
+                                      &pDirNode->NameInformation.FileName);
+
+                        //
+                        // Delete this dir entry and continue on
+                        //
 
-                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                  AFS_TRACE_LEVEL_VERBOSE,
-                                  "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
-                                  pDirNode,
-                                  &pDirNode->NameInformation.FileName);
+                        AFSDeleteDirEntry( ObjectInfoCB,
+                                           pDirNode);
+
+                        pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
+
+                        if( ulResultLen >= ulEntryLength)
+                        {
+                            ulResultLen -= ulEntryLength;
+                        }
+                        else
+                        {
+                            ulResultLen = 0;
+                        }
+
+                        continue;
+                    }
+                    else
+                    {
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
+                                      pDirNode,
+                                      &pDirNode->NameInformation.FileName);
+                    }
                 }
 
+                ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
+
                 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
                 {
 
@@ -1025,18 +1131,32 @@ AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
                                       "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
                                       pDirNode,
                                       &pDirNode->NameInformation.FileName);
+
+                        SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
                     }
                     else
                     {
 
-                        AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
-                                                    pDirNode);
+                        if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
+                                                                     pDirNode)))
+                        {
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
+                                          pDirNode,
+                                          pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
+                                          &pDirNode->NameInformation.FileName);
+                        }
+                        else
+                        {
+                            SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
 
-                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                      AFS_TRACE_LEVEL_VERBOSE,
-                                      "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
-                                      pDirNode,
-                                      &pDirNode->NameInformation.FileName);
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
+                                          pDirNode,
+                                          &pDirNode->NameInformation.FileName);
+                        }
                     }
                 }
 
@@ -1589,14 +1709,59 @@ AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
         if( DirectoryCB->NameInformation.ShortNameLength > 0)
         {
 
+            UNICODE_STRING uniShortName;
+
+            uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
+            uniShortName.MaximumLength = uniShortName.Length;
+            uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
+                          &uniShortName,
+                          DirectoryCB,
+                          &DirectoryCB->NameInformation.FileName);
+
+            DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
+
             RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
                            pRenameResultCB->DirEnum.ShortName,
                            DirectoryCB->NameInformation.ShortNameLength);
+
+            uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
+            uniShortName.MaximumLength = uniShortName.Length;
+            uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
+                          &uniShortName,
+                          DirectoryCB,
+                          &DirectoryCB->NameInformation.FileName);
+        }
+        else
+        {
+
+            UNICODE_STRING uniShortName;
+
+            uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
+            uniShortName.MaximumLength = uniShortName.Length;
+            uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
+                          &uniShortName,
+                          DirectoryCB,
+                          &DirectoryCB->NameInformation.FileName);
+
+            DirectoryCB->NameInformation.ShortNameLength = 0;
+
+            DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
         }
 
         if( UpdatedFID != NULL)
         {
-
             *UpdatedFID = pRenameResultCB->DirEnum.FileId;
         }
 
index e9412e4..0143aed 100644 (file)
@@ -1776,6 +1776,43 @@ AFSProcessCreate( IN PIRP               Irp,
 
         pObjectInfo = pDirEntry->ObjectInformation;
 
+        if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
+            pObjectInfo->FileType == AFS_FILE_TYPE_UNKNOWN)
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSProcessCreate (%08lX) Evaluating object %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                          Irp,
+                          &pDirEntry->NameInformation.FileName,
+                          pObjectInfo->FileId.Cell,
+                          pObjectInfo->FileId.Volume,
+                          pObjectInfo->FileId.Vnode,
+                          pObjectInfo->FileId.Unique);
+
+            ntStatus = AFSEvaluateNode( AuthGroup,
+                                        pDirEntry);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessCreate (%08lX) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                              Irp,
+                              &pDirEntry->NameInformation.FileName,
+                              pObjectInfo->FileId.Cell,
+                              pObjectInfo->FileId.Volume,
+                              pObjectInfo->FileId.Vnode,
+                              pObjectInfo->FileId.Unique,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+
+            ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
+        }
+
         //
         // We may have raced and the Fcb is already created
         //
@@ -2030,8 +2067,24 @@ try_exit:
                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                 TRUE);
 
-                AFSDeleteDirEntry( pParentObjectInfo,
-                                   pDirEntry);
+                SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
+
+                //
+                // Pull the directory entry from the parent
+                //
+
+                AFSRemoveDirNodeFromParent( pParentObjectInfo,
+                                            pDirEntry,
+                                            FALSE); // Leave it in the enum list so the worker cleans it up
+
+                AFSNotifyDelete( pDirEntry,
+                                 FALSE);
+
+                //
+                // Tag the parent as needing verification
+                //
+
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
             }
index ca759ff..7cf9da4 100644 (file)
@@ -262,16 +262,75 @@ AFSQueryDirectory( IN PIRP Irp)
         }
 
         //
-        // Grab the directory node hdr tree lock shared while parsing the directory
+        // Grab the directory node hdr tree lock while parsing the directory
         // contents
         //
 
-        AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                          TRUE);
+        AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                        TRUE);
 
         bReleaseMain = TRUE;
 
         //
+        // Before attempting to insert the new entry, check if we need to validate the parent
+        //
+
+        if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                          &pCcb->DirectoryCB->NameInformation.FileName,
+                          pFcb->ObjectInformation->FileId.Cell,
+                          pFcb->ObjectInformation->FileId.Volume,
+                          pFcb->ObjectInformation->FileId.Vnode,
+                          pFcb->ObjectInformation->FileId.Unique);
+
+            ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
+                                       pCcb->DirectoryCB);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSQueryDirectory Failed to verify parent %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);
+
+                try_return( ntStatus);
+            }
+
+            //
+            // Perform a new snapshot of the directory
+            //
+
+            ntStatus = AFSSnapshotDirectory( pFcb,
+                                             pCcb,
+                                             FALSE);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
+                              &pCcb->DirectoryCB->NameInformation.FileName,
+                              &pCcb->MaskName,
+                              ntStatus);
+
+                try_return( ntStatus);
+            }
+        }
+
+        AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+        //
         // We can now safely drop the lock on the node
         //
 
@@ -295,7 +354,8 @@ AFSQueryDirectory( IN PIRP Irp)
         {
 
             ntStatus = AFSSnapshotDirectory( pFcb,
-                                             pCcb);
+                                             pCcb,
+                                             TRUE);
 
             if( !NT_SUCCESS( ntStatus))
             {
@@ -540,7 +600,7 @@ AFSQueryDirectory( IN PIRP Irp)
                               FileInformationClass);
 
                 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
-            }
+        }
 
         AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
@@ -595,6 +655,8 @@ AFSQueryDirectory( IN PIRP Irp)
                      BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
             {
 
+                InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 continue;
             }
 
@@ -617,6 +679,8 @@ AFSQueryDirectory( IN PIRP Irp)
                     if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
                     {
 
+                        InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                         continue;
                     }
                 }
@@ -636,6 +700,8 @@ AFSQueryDirectory( IN PIRP Irp)
                                                       NULL))
                         {
 
+                            InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                             continue;
                         }
                     }
@@ -656,6 +722,8 @@ AFSQueryDirectory( IN PIRP Irp)
                                                          TRUE))
                             {
 
+                                InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                                 continue;
                             }
                         }
@@ -729,6 +797,8 @@ AFSQueryDirectory( IN PIRP Irp)
 
                 pCcb->CurrentDirIndex--;
 
+                InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 try_return( ntStatus = STATUS_SUCCESS);
             }
 
@@ -849,6 +919,8 @@ AFSQueryDirectory( IN PIRP Irp)
                                   Irp,
                                   FileInformationClass);
 
+                    InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                     try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
 
                     break;
@@ -874,9 +946,13 @@ AFSQueryDirectory( IN PIRP Irp)
             if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
             {
 
+                InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
             }
 
+            InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
             dStatus = STATUS_SUCCESS;
 
             //  Set ourselves up for the next iteration
@@ -1109,6 +1185,9 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
             // Get to a valid entry
             //
 
+            AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                              TRUE);
+
             while( ulCount < pSnapshotHdr->EntryCount)
             {
 
@@ -1145,6 +1224,8 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
                                       ObjectInfo->FileId.Volume,
                                       ObjectInfo->FileId.Vnode,
                                       ObjectInfo->FileId.Unique);
+
+                        InterlockedIncrement( &pDirEntry->OpenReferenceCount);
                     }
                     else
                     {
@@ -1177,6 +1258,8 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
                 Ccb->CurrentDirIndex++;
             }
+
+            AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
 
 try_exit:
@@ -1281,7 +1364,8 @@ try_exit:
 
 NTSTATUS
 AFSSnapshotDirectory( IN AFSFcb *Fcb,
-                      IN AFSCcb *Ccb)
+                      IN AFSCcb *Ccb,
+                      IN BOOLEAN ResetIndex)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
@@ -1292,19 +1376,23 @@ AFSSnapshotDirectory( IN AFSFcb *Fcb,
     __Enter
     {
 
-        //
-        // Set it up so we still get the . and .. entries for empty directories
-        //
-
-        if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
+        if( ResetIndex)
         {
 
-            Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
-        }
-        else
-        {
+            //
+            // Set it up so we still get the . and .. entries for empty directories
+            //
+
+            if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
+            {
+
+                Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
+            }
+            else
+            {
 
-            Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
+                Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
+            }
         }
 
         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)
index bc7967c..c08a020 100644 (file)
@@ -1746,12 +1746,13 @@ AFSSetRenameInfo( IN PIRP Irp)
     AFSObjectInfoCB *pSrcObject = NULL, *pTargetObject = NULL;
     AFSObjectInfoCB *pSrcParentObject = NULL, *pTargetParentObject = NULL;
     AFSFileID stNewFid, stTmpTargetFid;
-    UNICODE_STRING uniTmpTargetName;
-    BOOLEAN bReplaceTmpTargetEntry = FALSE;
     ULONG ulNotificationAction = 0, ulNotifyFilter = 0;
     UNICODE_STRING uniFullTargetPath;
     BOOLEAN bCommonParent = FALSE;
     ULONG oldFileIndex;
+    BOOLEAN bReleaseVolumeLock = FALSE;
+    BOOLEAN bReleaseTargetDirLock = FALSE;
+    BOOLEAN bReleaseSourceDirLock = FALSE;
 
     __Enter
     {
@@ -1763,10 +1764,6 @@ AFSSetRenameInfo( IN PIRP Irp)
 
         pSrcObject = pSrcFcb->ObjectInformation;
 
-        uniTmpTargetName.Length = 0;
-        uniTmpTargetName.MaximumLength = 0;
-        uniTmpTargetName.Buffer = NULL;
-
         //
         // Perform some basic checks to ensure FS integrity
         //
@@ -1879,14 +1876,26 @@ AFSSetRenameInfo( IN PIRP Irp)
         // If the target exists be sure the ReplaceIfExists flag is set
         //
 
-        AFSAcquireShared( pTargetParentObject->VolumeCB->VolumeLock,
-                          TRUE);
+        AFSAcquireExcl( pTargetParentObject->VolumeCB->VolumeLock,
+                        TRUE);
+
+        bReleaseVolumeLock = TRUE;
 
         ulTargetCRC = AFSGenerateCRC( &uniTargetName,
                                       FALSE);
 
-        AFSAcquireShared( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                          TRUE);
+        AFSAcquireExcl( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                        TRUE);
+
+        bReleaseTargetDirLock = TRUE;
+
+        if( pTargetParentObject != pSrcFcb->ObjectInformation->ParentObjectInformation)
+        {
+            AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                            TRUE);
+
+            bReleaseSourceDirLock = TRUE;
+        }
 
         AFSLocateCaseSensitiveDirEntry( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
                                         ulTargetCRC,
@@ -1918,25 +1927,21 @@ AFSSetRenameInfo( IN PIRP Irp)
                                         ulTargetCRC,
                                         &pTargetDirEntry);
         }
+
         //
         // Increment our ref count on the dir entry
         //
 
         if( pTargetDirEntry != NULL)
         {
-            InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
-        }
 
-        AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
+            ASSERT( pTargetParentObject == pTargetDirEntry->ObjectInformation->ParentObjectInformation);
 
-        if( pTargetDirEntry != NULL)
-        {
+            InterlockedIncrement( &pTargetDirEntry->OpenReferenceCount);
 
             if( !bReplaceIfExists)
             {
 
-                AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
-
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
                               "AFSSetRenameInfo Attempt to rename directory with target collision %wZ Target %wZ\n",
@@ -1953,10 +1958,22 @@ AFSSetRenameInfo( IN PIRP Irp)
                           pTargetDirEntry,
                           pTargetDirEntry->OpenReferenceCount);
 
+            //
+            // Pull the directory entry from the parent
+            //
+
+            AFSRemoveDirNodeFromParent( pTargetParentObject,
+                                        pTargetDirEntry,
+                                        FALSE);
+
             bTargetEntryExists = TRUE;
         }
-
-        AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
+        else
+        {
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSSetRenameInfo Target Target does NOT exist, normal rename\n");
+        }
 
         //
         // Extract off the final component name from the Fcb
@@ -1980,29 +1997,9 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             if( FsRtlAreNamesEqual( &uniTargetName,
                                     &uniSourceName,
-                                    TRUE,
+                                    FALSE,
                                     NULL))
             {
-
-                //
-                // Check for case only rename
-                //
-
-                if( !FsRtlAreNamesEqual( &uniTargetName,
-                                         &uniSourceName,
-                                         FALSE,
-                                         NULL))
-                {
-
-                    //
-                    // Just move in the new case form of the name
-                    //
-
-                    RtlCopyMemory( pSrcCcb->DirectoryCB->NameInformation.FileName.Buffer,
-                                   uniTargetName.Buffer,
-                                   uniTargetName.Length);
-                }
-
                 try_return( ntStatus = STATUS_SUCCESS);
             }
         }
@@ -2013,123 +2010,17 @@ AFSSetRenameInfo( IN PIRP Irp)
         }
 
         //
-        // If the target name exists then we need to 'move' the target before
-        // sending the rename to the service
-        //
-
-        if( bReplaceIfExists &&
-            pTargetDirEntry != NULL)
-        {
-
-            //
-            // What we will do is temporarily rename the file to a tmp file
-            // so we can back out if anything fails below
-            // First thing is to remove the original target from the parent
-            //
-
-            AFSAcquireExcl( pTargetDirEntry->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                            TRUE);
-
-            AFSRemoveDirNodeFromParent( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
-                                        pTargetDirEntry,
-                                        TRUE);
-
-            AFSReleaseResource( pTargetDirEntry->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
-
-            pTargetDirEntry->FileIndex = (ULONG)InterlockedIncrement( &pTargetDirEntry->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.ContentIndex);
-
-            uniTmpTargetName.Length = 0;
-            uniTmpTargetName.MaximumLength = uniTargetName.Length + (4 * sizeof( WCHAR));
-
-            uniTmpTargetName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
-                                                                         uniTmpTargetName.MaximumLength,
-                                                                         AFS_GENERIC_MEMORY_11_TAG);
-
-            if( uniTmpTargetName.Buffer == NULL)
-            {
-
-                //
-                // Re-insert the entry
-                //
-
-                AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
-                                        pTargetDirEntry,
-                                        TRUE);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Failed tmp buffer allocation during rename of %wZ\n",
-                              &pSrcCcb->DirectoryCB->NameInformation.FileName);
-
-                try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-            }
-
-            RtlZeroMemory( uniTmpTargetName.Buffer,
-                           uniTmpTargetName.MaximumLength);
-
-            uniTmpTargetName.Length = uniTargetName.Length;
-
-            RtlCopyMemory( uniTmpTargetName.Buffer,
-                           uniTargetName.Buffer,
-                           uniTmpTargetName.Length);
-
-            RtlCopyMemory( &uniTmpTargetName.Buffer[ uniTmpTargetName.Length/sizeof( WCHAR)],
-                           L".tmp",
-                           4 * sizeof( WCHAR));
-
-            uniTmpTargetName.Length += (4 * sizeof( WCHAR));
-
-            ntStatus = AFSNotifyRename( pTargetDirEntry->ObjectInformation,
-                                        pTargetDirEntry->ObjectInformation->ParentObjectInformation,
-                                        pTargetDcb->ObjectInformation,
-                                        pTargetDirEntry,
-                                        &uniTmpTargetName,
-                                        &stTmpTargetFid);
-
-            if( !NT_SUCCESS( ntStatus))
-            {
-
-                //
-                // Re-insert the entry
-                //
-
-                AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
-                                        pTargetDirEntry,
-                                        TRUE);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Failed rename of %wZ to tmp %wZ Status %08lX\n",
-                              &pSrcCcb->DirectoryCB->NameInformation.FileName,
-                              &uniTmpTargetName,
-                              ntStatus);
-
-                try_return( ntStatus);
-            }
-
-            //
-            // Indicate we need to replace this entry if any failure occurs below
-            //
-
-            bReplaceTmpTargetEntry = TRUE;
-        }
-
-        //
         // 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
         //
 
-        AFSAcquireExcl( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                        TRUE);
-
         AFSRemoveDirNodeFromParent( pSrcFcb->ObjectInformation->ParentObjectInformation,
                                     pSrcCcb->DirectoryCB,
                                     !bCommonParent);
 
-        AFSReleaseResource( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
-
         oldFileIndex = pSrcCcb->DirectoryCB->FileIndex;
+
         if( !bCommonParent)
         {
 
@@ -2182,7 +2073,7 @@ AFSSetRenameInfo( IN PIRP Irp)
         //
 
         if( pSrcCcb->DirectoryCB->ObjectInformation->ParentObjectInformation == pTargetParentObject &&
-            !bReplaceTmpTargetEntry)
+            !bTargetEntryExists)
         {
 
             ulNotificationAction = FILE_ACTION_RENAMED_OLD_NAME;
@@ -2250,9 +2141,6 @@ AFSSetRenameInfo( IN PIRP Irp)
             // Remove the old information entry
             //
 
-            AFSAcquireExcl( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock,
-                            TRUE);
-
             AFSRemoveHashEntry( &pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
                                 &pSrcObject->TreeEntry);
 
@@ -2277,8 +2165,6 @@ AFSSetRenameInfo( IN PIRP Irp)
                 AFSInsertHashEntry( pSrcObject->VolumeCB->ObjectInfoTree.TreeHead,
                                     &pSrcObject->TreeEntry);
             }
-
-            AFSReleaseResource( pSrcObject->VolumeCB->ObjectInfoTree.TreeLock);
         }
 
         //
@@ -2291,10 +2177,14 @@ AFSSetRenameInfo( IN PIRP Irp)
         pSrcCcb->DirectoryCB->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pSrcCcb->DirectoryCB->NameInformation.FileName,
                                                                                    TRUE);
 
-        if( pSrcCcb->DirectoryCB->NameInformation.ShortNameLength > 0)
+        if( 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,
@@ -2369,49 +2259,9 @@ AFSSetRenameInfo( IN PIRP Irp)
         // delete the tmp target we created above
         //
 
-        if( bReplaceTmpTargetEntry)
+        if( bTargetEntryExists)
         {
 
-            RtlCopyMemory( &pTargetDirEntry->ObjectInformation->FileId,
-                           &stTmpTargetFid,
-                           sizeof( AFSFileID));
-
-            //
-            // Update the name in the dir entry
-            //
-
-            ntStatus = AFSUpdateDirEntryName( pTargetDirEntry,
-                                              &uniTmpTargetName);
-
-            if( !NT_SUCCESS( ntStatus))
-            {
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSSetRenameInfo Failed update of target dir entry %wZ to tmp %wZ Status %08lX\n",
-                              &pTargetDirEntry->NameInformation.FileName,
-                              &uniTmpTargetName,
-                              ntStatus);
-
-                try_return( ntStatus);
-            }
-
-            ntStatus = AFSNotifyDelete( pTargetDirEntry,
-                                        FALSE);
-
-            if( !NT_SUCCESS( ntStatus))
-            {
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSSetRenameInfo object deletion failure dir entry %p name %wZ to tmp %wZ\n",
-                              pTargetDirEntry,
-                              &pTargetDirEntry->NameInformation.FileName,
-                              &uniTmpTargetName);
-
-                try_return( ntStatus);
-            }
-
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSSetRenameInfo Setting DELETE flag in dir entry %p name %wZ\n",
@@ -2435,11 +2285,11 @@ AFSSetRenameInfo( IN PIRP Irp)
                                 TRUE);
 
                 //
-                // Try and flush the cache map
+                // Close the section in the event it was mapped
                 //
 
-                if( !MmFlushImageSection( &pTargetFcb->NPFcb->SectionObjectPointers,
-                                          MmFlushForDelete))
+                if( !MmForceSectionClosed( &pTargetFcb->NPFcb->SectionObjectPointers,
+                                           TRUE))
                 {
 
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -2453,54 +2303,19 @@ AFSSetRenameInfo( IN PIRP Irp)
 
             ASSERT( pTargetDirEntry->OpenReferenceCount > 0);
 
-            InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
+            InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount); // The count we added above
 
             if( pTargetDirEntry->OpenReferenceCount == 0)
             {
 
-                SetFlag( pTargetDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
-
-                ASSERT( BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE));
-
-                //
-                // Free up the name buffer if it was reallocated
-                //
-
-                if( BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
-                {
-
-                    AFSExFreePool( pTargetDirEntry->NameInformation.FileName.Buffer);
-                }
-
-                if( BooleanFlagOn( pTargetDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
-                {
-
-                    AFSExFreePool( pTargetDirEntry->NameInformation.TargetName.Buffer);
-                }
-
-                //
-                // Dereference the object for this dir entry
-                //
-
-                ASSERT( pTargetDirEntry->ObjectInformation->ObjectReferenceCount > 0);
-
-                InterlockedDecrement( &pTargetDirEntry->ObjectInformation->ObjectReferenceCount);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSSetRenameInfo Decrement3 count on object %08lX Cnt %d\n",
-                              pTargetDirEntry->ObjectInformation,
-                              pTargetDirEntry->ObjectInformation->ObjectReferenceCount);
-
-                //
-                // Free up the dir entry
-                //
-
-                ExDeleteResourceLite( &pTargetDirEntry->NonPaged->Lock);
-
-                AFSExFreePool( pTargetDirEntry->NonPaged);
+                              "AFSSetRenameInfo Deleting dir entry %p name %wZ\n",
+                              pTargetDirEntry,
+                              &pTargetDirEntry->NameInformation.FileName);
 
-                AFSExFreePool( pTargetDirEntry);
+                AFSDeleteDirEntry( pTargetParentObject,
+                                   pTargetDirEntry);
             }
 
             pTargetDirEntry = NULL;
@@ -2512,46 +2327,11 @@ try_exit:
         if( !NT_SUCCESS( ntStatus))
         {
 
-            if( bReplaceTmpTargetEntry)
+            if( bTargetEntryExists)
             {
-
-                AFSNotifyRename( pTargetDirEntry->ObjectInformation,
-                                 pTargetDirEntry->ObjectInformation->ParentObjectInformation,
-                                 pTargetDcb->ObjectInformation,
-                                 pTargetDirEntry,
-                                 &uniTargetName,
-                                 &stTmpTargetFid);
-
-                //
-                // Replace the target entry
-                //
-
-                AFSAcquireExcl( pTargetDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
-                                TRUE);
-
-                if( pTargetDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead == NULL)
-                {
-
-                    pTargetDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead = &pTargetDirEntry->ObjectInformation->TreeEntry;
-                }
-                else
-                {
-                    AFSInsertHashEntry( pTargetDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead,
-                                        &pTargetDirEntry->ObjectInformation->TreeEntry);
-                }
-
-                AFSReleaseResource( pTargetDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
-
-                //
-                // We always need to update the FileIndex since this entry will be put at the 'end'
-                // of the enumeraiton list. If we don't it will cause recursion ...
-                //
-
-                pTargetDirEntry->FileIndex = (ULONG)InterlockedIncrement( &pTargetDirEntry->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.ContentIndex);
-
                 AFSInsertDirectoryNode( pTargetDirEntry->ObjectInformation->ParentObjectInformation,
                                         pTargetDirEntry,
-                                        TRUE);
+                                        FALSE);
             }
         }
 
@@ -2561,10 +2341,19 @@ try_exit:
             InterlockedDecrement( &pTargetDirEntry->OpenReferenceCount);
         }
 
-        if( uniTmpTargetName.Buffer != NULL)
+        if( bReleaseVolumeLock)
         {
+            AFSReleaseResource( pTargetParentObject->VolumeCB->VolumeLock);
+        }
 
-            AFSExFreePool( uniTmpTargetName.Buffer);
+        if( bReleaseTargetDirLock)
+        {
+            AFSReleaseResource( pTargetParentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
+        }
+
+        if( bReleaseSourceDirLock)
+        {
+            AFSReleaseResource( pSrcFcb->ObjectInformation->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
     }
 
index 4251e74..3fa2e59 100644 (file)
@@ -1022,10 +1022,10 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
         pDirNode->ObjectInformation = pObjectInfoCB;
 
         //
-        // Set valid entry
+        // Set valid entry and NOT_IN_PARENT flag
         //
 
-        SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
+        SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
 
         pDirNode->FileIndex = FileIndex;
 
@@ -3246,20 +3246,62 @@ AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
         while( pCurrentDirEntry != NULL)
         {
 
+            pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
+
             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
             {
 
-                ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
+                //
+                // If this entry has been deleted then process it here
+                //
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
-                              pCurrentDirEntry,
-                              pCurrentDirEntry->OpenReferenceCount);
+                if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
+                    pCurrentDirEntry->OpenReferenceCount == 0)
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
+                                  pCurrentDirEntry,
+                                  &pCurrentDirEntry->NameInformation.FileName);
+
+                    AFSDeleteDirEntry( ObjectInfo,
+                                       pCurrentDirEntry);
+                }
+                else
+                {
+
+                    ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
 
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
+                                  pCurrentDirEntry,
+                                  pCurrentDirEntry->OpenReferenceCount);
+
+                    //
+                    // We pull the short name from the parent tree since it could change below
+                    //
+
+                    if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
+                    {
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
+                                      pCurrentDirEntry,
+                                      pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
+                                      &pCurrentDirEntry->NameInformation.FileName);
+
+                        AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
+                                                    pCurrentDirEntry);
+
+                        ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
+                    }
+                }
             }
 
-            pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
+            pCurrentDirEntry = pNextDirEntry;
         }
 
         //
@@ -3283,6 +3325,49 @@ AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
             {
 
+                if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
+                    pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
+                {
+
+                    if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
+                    {
+
+                        ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
+
+                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                      AFS_TRACE_LEVEL_VERBOSE,
+                                      "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
+                                      pCurrentDirEntry,
+                                      &pCurrentDirEntry->NameInformation.FileName);
+
+                        SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
+                    }
+                    else
+                    {
+
+                        if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
+                                                                     pCurrentDirEntry)))
+                        {
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
+                                          pCurrentDirEntry,
+                                          pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
+                                          &pCurrentDirEntry->NameInformation.FileName);
+                        }
+                        else
+                        {
+                            SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
+                                          pCurrentDirEntry,
+                                          &pCurrentDirEntry->NameInformation.FileName);
+                        }
+                    }
+                }
+
                 pCurrentDirEntry = pNextDirEntry;
 
                 continue;
@@ -6958,8 +7043,7 @@ AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
                                           DirEntry);
 
-        if( ParentObjectInfo->Specific.Directory.ShortNameTree &&
-            DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
+        if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
         {
 
             //
@@ -6974,6 +7058,8 @@ AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
                                         DirEntry);
+
+            ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
         }
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -6984,6 +7070,8 @@ AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
 
+        ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+
 try_exit:
 
         NOTHING;
@@ -7119,7 +7207,7 @@ AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
 
     BOOLEAN bIsValid = TRUE;
     ULONG ulCount = 0;
-    AFSDirectoryCB *pCurrentDirEntry = NULL;
+    AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
 
     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
 
@@ -7129,6 +7217,21 @@ AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
         {
             ulCount++;
+
+            if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
+            {
+
+                pDirEntry = NULL;
+
+                AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                                (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
+                                                &pDirEntry);
+
+                if( pDirEntry == NULL)
+                {
+                    DbgBreakPoint();
+                }
+            }
         }
 
         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
index f4fad07..26b6e51 100644 (file)
@@ -1943,7 +1943,7 @@ AFSCreateDirEntry( IN GUID            *AuthGroup,
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    AFSDirectoryCB *pDirNode = NULL;
+    AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
     UNICODE_STRING uniShortName;
     LARGE_INTEGER liFileSize = {0,0};
 
@@ -2005,6 +2005,68 @@ AFSCreateDirEntry( IN GUID            *AuthGroup,
             try_return( ntStatus);
         }
 
+        AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                        TRUE);
+
+        //
+        // Before attempting to insert the new entry, check if we need to validate the parent
+        //
+
+        if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                          &ParentDirCB->NameInformation.FileName,
+                          ParentObjectInfo->FileId.Cell,
+                          ParentObjectInfo->FileId.Volume,
+                          ParentObjectInfo->FileId.Vnode,
+                          ParentObjectInfo->FileId.Unique);
+
+            ntStatus = AFSVerifyEntry( AuthGroup,
+                                       ParentDirCB);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                              &ParentDirCB->NameInformation.FileName,
+                              ParentObjectInfo->FileId.Cell,
+                              ParentObjectInfo->FileId.Volume,
+                              ParentObjectInfo->FileId.Vnode,
+                              ParentObjectInfo->FileId.Unique,
+                              ntStatus);
+
+                AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                try_return( ntStatus);
+            }
+        }
+
+        //
+        // Check for the entry in the event we raced with some other thread
+        //
+
+        AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
+                                        (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
+                                        &pExistingDirNode);
+
+        if( pExistingDirNode != NULL)
+        {
+
+            AFSDeleteDirEntry( ParentObjectInfo,
+                               pDirNode);
+
+            *DirEntry = pExistingDirNode;
+
+            AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+            try_return( ntStatus = STATUS_SUCCESS);
+        }
+
         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE_2,
                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
@@ -2029,6 +2091,8 @@ AFSCreateDirEntry( IN GUID            *AuthGroup,
 
         *DirEntry = pDirNode;
 
+        AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
 try_exit:
 
         NOTHING;
@@ -2046,8 +2110,7 @@ AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
     __Enter
     {
 
-        AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                        TRUE);
+        ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
 
         //
         // Insert the node into the directory node tree
@@ -2128,18 +2191,31 @@ AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
                               DirEntry,
                               &DirEntry->NameInformation.FileName);
+
+                SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
             }
             else
             {
 
-                AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
-                                            DirEntry);
+                if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
+                                                             DirEntry)))
+                {
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
+                                  DirEntry,
+                                  &DirEntry->NameInformation.FileName);
+                }
+                else
+                {
+                    SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
-                              DirEntry,
-                              &DirEntry->NameInformation.FileName);
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
+                                  DirEntry,
+                                  &DirEntry->NameInformation.FileName);
+                }
             }
         }
 
@@ -2189,8 +2265,6 @@ AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
                               ParentObjectInfo->FileId.Vnode,
                               ParentObjectInfo->FileId.Unique);
         }
-
-        AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
     }
 
     return;
@@ -2243,7 +2317,10 @@ AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
         ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
 
-        InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount);
+        if( InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount) == 0)
+        {
+            SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
+        }
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
@@ -3707,10 +3784,21 @@ AFSCheckCellName( IN GUID *AuthGroup,
             else
             {
 
-                AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
-                                                pDirNode);
+                if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
+                                                                 pDirNode)))
+                {
+
+                    AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
+                                       pDirNode);
+
+                    AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+                }
             }
 
+            ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
+
             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
             {
 
index cdaa8e1..24125fa 100644 (file)
@@ -885,7 +885,8 @@ AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
 
 NTSTATUS
 AFSSnapshotDirectory( IN AFSFcb *Fcb,
-                      IN AFSCcb *Ccb);
+                      IN AFSCcb *Ccb,
+                      IN BOOLEAN ResetIndex);
 
 NTSTATUS
 AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
index 0b88e0b..8107ea7 100644 (file)
@@ -244,6 +244,7 @@ NTSTATUS
 #define AFS_DIR_ENTRY_SERVER_SERVICE            0x00000400
 #define AFS_DIR_ENTRY_WORKSTATION_SERVICE       0x00000800
 #define AFS_DIR_ENTRY_IPC                       0x00001000
+#define AFS_DIR_ENTRY_INSERTED_SHORT_NAME       0x00002000
 
 //
 // Network provider errors