Windows: Make CCB_FLAGS_DIRECTORY_QUERY_MAPPED consistent
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSDirControl.cpp
index ca759ff..d9e3e96 100644 (file)
@@ -89,12 +89,14 @@ AFSDirControl( IN PDEVICE_OBJECT LibDeviceObject,
                 break;
         }
     }
-    __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
     {
 
         AFSDbgLogMsg( 0,
                       0,
                       "EXCEPTION - AFSDirControl\n");
+
+        AFSDumpTraceFilesFnc();
     }
 
     if( ntStatus != STATUS_PENDING)
@@ -141,11 +143,13 @@ AFSQueryDirectory( IN PIRP Irp)
     ULONG ulBytesConverted;
     AFSDirectoryCB *pDirEntry = NULL;
     BOOLEAN bReleaseMain = FALSE;
+    BOOLEAN bReleaseFcb = FALSE;
     ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN;
     AFSFileInfoCB       stFileInfo;
     BOOLEAN         bUseFileInfo = TRUE;
     AFSObjectInfoCB *pObjectInfo = NULL;
     ULONG ulAdditionalAttributes = 0;
+    LONG lCount;
 
     __Enter
     {
@@ -202,7 +206,7 @@ AFSQueryDirectory( IN PIRP Irp)
         bReturnSingleEntry = BooleanFlagOn( pIrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
         bIndexSpecified    = BooleanFlagOn( pIrpSp->Flags, SL_INDEX_SPECIFIED);
 
-        bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED));
+        bInitialQuery = (BOOLEAN)( !BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED));
 
         if( bInitialQuery)
         {
@@ -221,27 +225,7 @@ AFSQueryDirectory( IN PIRP Irp)
             AFSAcquireExcl( &pFcb->NPFcb->Resource,
                             TRUE);
 
-            //
-            // Tell the service to prime the cache of the directory content
-            //
-
-            ntStatus = AFSEnumerateDirectoryNoResponse( &pFcb->AuthGroup,
-                                                        &pFcb->ObjectInformation->FileId);
-
-            if( !NT_SUCCESS( ntStatus))
-            {
-
-                AFSReleaseResource( &pFcb->NPFcb->Resource);
-
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_ERROR,
-                              "AFSQueryDirectory Enumerate directory failure for parent %wZ Mask %wZ Status %08lX\n",
-                              &pCcb->DirectoryCB->NameInformation.FileName,
-                              &pCcb->MaskName,
-                              ntStatus);
-
-                try_return( ntStatus);
-            }
+            bReleaseFcb = TRUE;
         }
         else
         {
@@ -259,24 +243,87 @@ AFSQueryDirectory( IN PIRP Irp)
 
             AFSAcquireShared( &pFcb->NPFcb->Resource,
                               TRUE);
+
+            bReleaseFcb = TRUE;
         }
 
         //
-        // 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( &pCcb->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
         //
 
         AFSReleaseResource( &pFcb->NPFcb->Resource);
 
+        bReleaseFcb = FALSE;
+
         //
         // Start processing the data
         //
@@ -295,7 +342,8 @@ AFSQueryDirectory( IN PIRP Irp)
         {
 
             ntStatus = AFSSnapshotDirectory( pFcb,
-                                             pCcb);
+                                             pCcb,
+                                             TRUE);
 
             if( !NT_SUCCESS( ntStatus))
             {
@@ -310,7 +358,7 @@ AFSQueryDirectory( IN PIRP Irp)
                 try_return( ntStatus);
             }
 
-            SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
+            SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
 
             ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
 
@@ -540,7 +588,7 @@ AFSQueryDirectory( IN PIRP Irp)
                               FileInformationClass);
 
                 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
-            }
+        }
 
         AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
@@ -595,6 +643,8 @@ AFSQueryDirectory( IN PIRP Irp)
                      BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
             {
 
+                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 continue;
             }
 
@@ -617,6 +667,8 @@ AFSQueryDirectory( IN PIRP Irp)
                     if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
                     {
 
+                        lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                         continue;
                     }
                 }
@@ -636,6 +688,8 @@ AFSQueryDirectory( IN PIRP Irp)
                                                       NULL))
                         {
 
+                            lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                             continue;
                         }
                     }
@@ -656,6 +710,8 @@ AFSQueryDirectory( IN PIRP Irp)
                                                          TRUE))
                             {
 
+                                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                                 continue;
                             }
                         }
@@ -669,8 +725,7 @@ AFSQueryDirectory( IN PIRP Irp)
             //
 
             AFSValidateEntry( pDirEntry,
-                              &pFcb->AuthGroup,
-                              FALSE,
+                              &pCcb->AuthGroup,
                               FALSE);
 
             pObjectInfo = pDirEntry->ObjectInformation;
@@ -695,9 +750,12 @@ AFSQueryDirectory( IN PIRP Irp)
                                                            pDirEntry,
                                                            &pCcb->FullFileName,
                                                            pCcb->NameArray,
+                                                           &pCcb->AuthGroup,
                                                            &stFileInfo)))
                 {
 
+                    ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
+
                     bUseFileInfo = TRUE;
                 }
             }
@@ -729,6 +787,8 @@ AFSQueryDirectory( IN PIRP Irp)
 
                 pCcb->CurrentDirIndex--;
 
+                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 try_return( ntStatus = STATUS_SUCCESS);
             }
 
@@ -748,7 +808,7 @@ AFSQueryDirectory( IN PIRP Irp)
                 //  Now fill the base parts of the structure that are applicable.
                 case FileIdBothDirectoryInformation:
                 case FileBothDirectoryInformation:
-
+                {
                     pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
 
                     pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
@@ -759,14 +819,15 @@ AFSQueryDirectory( IN PIRP Irp)
                                        &pDirEntry->NameInformation.ShortName[ 0],
                                        pBothDirInfo->ShortNameLength);
                     }
+                }
                 case FileIdFullDirectoryInformation:
                 case FileFullDirectoryInformation:
-
+                {
                     pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
                     pFullDirInfo->EaSize = 0;
-
+                }
                 case FileDirectoryInformation:
-
+                {
                     pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
 
                     if( bUseFileInfo)
@@ -780,7 +841,7 @@ AFSQueryDirectory( IN PIRP Irp)
                         pDirInfo->EndOfFile = stFileInfo.EndOfFile;
                         pDirInfo->AllocationSize = stFileInfo.AllocationSize;
 
-                        pDirInfo->FileAttributes = stFileInfo.FileAttributes;
+                        pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
                     }
                     else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
                     {
@@ -832,26 +893,30 @@ AFSQueryDirectory( IN PIRP Irp)
                     pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
 
                     break;
+                }
 
                 case FileNamesInformation:
-
+                {
                     pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
                     pNamesInfo->FileIndex = pDirEntry->FileIndex;
                     pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
 
                     break;
-
+                }
                 default:
-
+                {
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                   AFS_TRACE_LEVEL_ERROR,
                                   "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
                                   Irp,
                                   FileInformationClass);
 
+                    lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                     try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
 
                     break;
+                }
             }
 
             ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
@@ -874,9 +939,13 @@ AFSQueryDirectory( IN PIRP Irp)
             if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
             {
 
+                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
                 try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
             }
 
+            lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
             dStatus = STATUS_SUCCESS;
 
             //  Set ourselves up for the next iteration
@@ -892,6 +961,12 @@ try_exit:
             AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
 
+        if ( bReleaseFcb)
+        {
+
+            AFSReleaseResource( &pFcb->NPFcb->Resource);
+        }
+
         if( pFcb != NULL)
         {
 
@@ -1014,6 +1089,7 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
     AFSSnapshotHdr *pSnapshotHdr = NULL;
     AFSSnapshotEntry *pSnapshotEntry = NULL;
     ULONG ulCount = 0;
+    LONG lCount;
 
     __Enter
     {
@@ -1031,6 +1107,12 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
                 pDirEntry = ObjectInfo->Specific.Directory.PIOCtlDirectoryCB;
 
+                if( pDirEntry != NULL)
+                {
+
+                    lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
+                }
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_VERBOSE,
                               "AFSLocateNextDirEntry Returning PIOctl entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
@@ -1057,6 +1139,12 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
             pDirEntry = AFSGlobalDotDirEntry;
 
+            if( pDirEntry != NULL)
+            {
+
+                lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
+            }
+
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSLocateNextDirEntry Returning1 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
@@ -1075,6 +1163,12 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
             pDirEntry = AFSGlobalDotDotDirEntry;
 
+            if( pDirEntry != NULL)
+            {
+
+                lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
+            }
+
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSLocateNextDirEntry Returning2 snapshot entry %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
@@ -1109,6 +1203,9 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
             // Get to a valid entry
             //
 
+            AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                              TRUE);
+
             while( ulCount < pSnapshotHdr->EntryCount)
             {
 
@@ -1145,6 +1242,8 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
                                       ObjectInfo->FileId.Volume,
                                       ObjectInfo->FileId.Vnode,
                                       ObjectInfo->FileId.Unique);
+
+                        lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
                     }
                     else
                     {
@@ -1177,6 +1276,8 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
                 Ccb->CurrentDirIndex++;
             }
+
+            AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
 
 try_exit:
@@ -1281,7 +1382,8 @@ try_exit:
 
 NTSTATUS
 AFSSnapshotDirectory( IN AFSFcb *Fcb,
-                      IN AFSCcb *Ccb)
+                      IN AFSCcb *Ccb,
+                      IN BOOLEAN ResetIndex)
 {
 
     NTSTATUS ntStatus = STATUS_SUCCESS;
@@ -1292,19 +1394,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
+            //
 
-            Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
+            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;
+            }
         }
 
         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)