Windows: Directory Entry Processing
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSGeneric.cpp
index 54b3b4f..3fa2e59 100644 (file)
@@ -324,43 +324,6 @@ AFSCompleteRequest( IN PIRP Irp,
 }
 
 //
-// Function: AFSBuildCRCTable
-//
-// Description:
-//
-//      This function builds the CRC table for mapping filenames to a CRC value.
-//
-// Return:
-//
-//      A status is returned for the function
-//
-
-void
-AFSBuildCRCTable()
-{
-    ULONG crc;
-    int i, j;
-
-    for ( i = 0; i <= 255; i++)
-    {
-        crc = i;
-        for ( j = 8; j > 0; j--)
-        {
-            if (crc & 1)
-            {
-                crc = ( crc >> 1 ) ^ CRC32_POLYNOMIAL;
-            }
-            else
-            {
-                crc >>= 1;
-            }
-        }
-
-        AFSCRCTable[ i ] = crc;
-    }
-}
-
-//
 // Function: AFSGenerateCRC
 //
 // Description:
@@ -377,54 +340,20 @@ AFSGenerateCRC( IN PUNICODE_STRING FileName,
                 IN BOOLEAN UpperCaseName)
 {
 
-    ULONG crc;
-    ULONG temp1, temp2;
-    UNICODE_STRING UpcaseString;
-    WCHAR *lpbuffer;
-    USHORT size = 0;
-
-    if( !AFSCRCTable[1])
-    {
-        AFSBuildCRCTable();
-    }
-
-    crc = 0xFFFFFFFFL;
-
-    if( UpperCaseName)
-    {
-
-        RtlUpcaseUnicodeString( &UpcaseString,
-                                FileName,
-                                TRUE);
-
-        lpbuffer = UpcaseString.Buffer;
-
-        size = (UpcaseString.Length/sizeof( WCHAR));
-    }
-    else
-    {
-
-        lpbuffer = FileName->Buffer;
-
-        size = (FileName->Length/sizeof( WCHAR));
-    }
+    ULONG ulCRC = 0;
+    NTSTATUS ntStatus = STATUS_SUCCESS;
 
-    while (size--)
-    {
-        temp1 = (crc >> 8) & 0x00FFFFFFL;
-        temp2 = AFSCRCTable[((int)crc ^ *lpbuffer++) & 0xff];
-        crc = temp1 ^ temp2;
-    }
+    ntStatus = RtlHashUnicodeString( FileName,
+                                     UpperCaseName,
+                                     HASH_STRING_ALGORITHM_DEFAULT,
+                                     &ulCRC);
 
-    if( UpperCaseName)
+    if( !NT_SUCCESS( ntStatus))
     {
-
-        RtlFreeUnicodeString( &UpcaseString);
+        ulCRC = 0;
     }
 
-    crc ^= 0xFFFFFFFFL;
-
-    return crc;
+    return ulCRC;
 }
 
 void *
@@ -1031,7 +960,7 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
 
             bAllocatedObjectCB = TRUE;
 
-            AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSInitDirEntry initialized object %08lX Parent Object %08lX for %wZ\n",
                           pObjectInfoCB,
@@ -1093,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;
 
@@ -1128,6 +1057,16 @@ AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
                                                                            TRUE);
         }
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
+                      pDirNode,
+                      FileName,
+                      ParentObjectInfo->FileId.Cell,
+                      ParentObjectInfo->FileId.Volume,
+                      ParentObjectInfo->FileId.Vnode,
+                      ParentObjectInfo->FileId.Unique);
+
         if( TargetName != NULL &&
             TargetName->Length > 0)
         {
@@ -1392,6 +1331,14 @@ AFSEvaluateNode( IN GUID *AuthGroup,
 
         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
 
+        if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
+            pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
+            pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
+        {
+
+            DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+        }
+
         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
 
         DirEntry->ObjectInformation->Links = pDirEntry->Links;
@@ -1564,6 +1511,14 @@ AFSValidateSymLink( IN GUID *AuthGroup,
 
         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
 
+        if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
+            pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
+            pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
+        {
+
+            DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+        }
+
         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
 
         DirEntry->ObjectInformation->Links = pDirEntry->Links;
@@ -3291,13 +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
+                //
+
+                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;
         }
 
         //
@@ -3321,11 +3325,60 @@ 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;
             }
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
+                          pCurrentDirEntry,
+                          pCurrentDirEntry->OpenReferenceCount);
+
             if( pCurrentDirEntry->OpenReferenceCount == 0)
             {
 
@@ -4008,7 +4061,7 @@ AFSInitializeSpecialShareNameList()
         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
-                                                    pObjectInfoCB);
+                      pObjectInfoCB);
 
         pObjectInfoCB->ObjectReferenceCount = 1;
 
@@ -4093,7 +4146,7 @@ AFSInitializeSpecialShareNameList()
         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSInitializeSpecialShareNameList (wkssvc) Initializing count (1) on object %08lX\n",
-                                                    pObjectInfoCB);
+                      pObjectInfoCB);
 
         pObjectInfoCB->ObjectReferenceCount = 1;
 
@@ -4180,7 +4233,7 @@ AFSInitializeSpecialShareNameList()
         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                       AFS_TRACE_LEVEL_VERBOSE,
                       "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
-                                                    pObjectInfoCB);
+                      pObjectInfoCB);
 
         pObjectInfoCB->ObjectReferenceCount = 1;
 
@@ -5411,8 +5464,7 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
 
         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
 
-        ulEntryLength = sizeof( AFSDirectoryCB) +
-                                     AFSPIOCtlName.Length;
+        ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
 
         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
                                                                ulEntryLength,
@@ -5433,10 +5485,6 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
         if( pNonPagedDirEntry == NULL)
         {
 
-            AFSExFreePool( pDirNode);
-
-            AFSDeleteObjectInfo( pObjectInfoCB);
-
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
 
@@ -5477,7 +5525,21 @@ AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
 
 try_exit:
 
-        NOTHING;
+        if ( !NT_SUCCESS( ntStatus))
+        {
+
+            if ( pDirNode != NULL)
+            {
+
+                AFSExFreePool( pDirNode);
+            }
+
+            if ( pObjectInfoCB != NULL)
+            {
+
+                AFSDeleteObjectInfo( pObjectInfoCB);
+            }
+        }
     }
 
     return ntStatus;
@@ -5937,14 +5999,14 @@ try_exit:
             // offset by the length of the server name
             //
 
-            AFSExFreePool( pwchBuffer);
-
             if( uniFullPathName.Length > 0 &&
                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
             {
 
                 AFSExFreePool( uniFullPathName.Buffer);
             }
+
+            AFSExFreePool( pwchBuffer);
         }
     }
 
@@ -6457,14 +6519,14 @@ try_exit:
             // offset by the length of the server name
             //
 
-            AFSExFreePool( pwchBuffer);
-
             if( uniFullPathName.Length > 0 &&
                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
             {
 
                 AFSExFreePool( uniFullPathName.Buffer);
             }
+
+            AFSExFreePool( pwchBuffer);
         }
     }
 
@@ -6948,6 +7010,12 @@ AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
         {
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
+                          DirEntry,
+                          &DirEntry->NameInformation.FileName);
+
             try_return( ntStatus);
         }
 
@@ -6957,26 +7025,53 @@ AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
         // Remove the entry from the parent tree
         //
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
+                      DirEntry,
+                      &DirEntry->NameInformation.FileName);
+
         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
                                         DirEntry);
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
+                      DirEntry,
+                      &DirEntry->NameInformation.FileName);
+
         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))
         {
 
             //
             // From the short name tree
             //
 
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
+                          DirEntry,
+                          &DirEntry->NameInformation.FileName);
+
             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
                                         DirEntry);
+
+            ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
         }
 
+        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                      AFS_TRACE_LEVEL_VERBOSE,
+                      "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
+                      DirEntry,
+                      &DirEntry->NameInformation.FileName);
+
         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
 
+        ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
+
 try_exit:
 
         NOTHING;
@@ -7112,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;
 
@@ -7122,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;