Windows: File Attribute Reporting Consistency
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSDirControl.cpp
index e7346f2..ba335bc 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
- * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
+ * Copyright (c) 2008-2013 Kernel Drivers, LLC.
+ * Copyright (c) 2009-2013 Your File System, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * - Redistributions of source code must retain the above copyright notice,
  *   this list of conditions and the following disclaimer.
  * - Redistributions in binary form must reproduce the above copyright
- *   notice,
- *   this list of conditions and the following disclaimer in the
- *   documentation
- *   and/or other materials provided with the distribution.
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
  *   nor the names of their contributors may be used to endorse or promote
  *   products derived from this software without specific prior written
@@ -54,11 +52,9 @@ NTSTATUS
 AFSDirControl( IN PDEVICE_OBJECT LibDeviceObject,
                IN PIRP Irp)
 {
-
+    UNREFERENCED_PARAMETER(LibDeviceObject);
     NTSTATUS ntStatus = STATUS_SUCCESS;
-    ULONG ulRequestType = 0;
     IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
-    AFSFcb *pFcb = NULL;
 
     __try
     {
@@ -120,21 +116,18 @@ AFSQueryDirectory( IN PIRP Irp)
     AFSFcb *pFcb = NULL;
     AFSCcb *pCcb = NULL;
     BOOLEAN bInitialQuery = FALSE;
-    ULONG ulIndex;
     PUCHAR pBuffer;
     ULONG ulUserBufferLength;
     PUNICODE_STRING puniArgFileName = NULL;
     UNICODE_STRING uniTmpMaskName;
-    UNICODE_STRING uniDirUniBuf;
     WCHAR wchMaskBuffer[ 4];
     FILE_INFORMATION_CLASS FileInformationClass;
-    ULONG ulFileIndex, ulDOSFileIndex;
+    ULONG ulFileIndex;
     BOOLEAN bRestartScan;
     BOOLEAN bReturnSingleEntry;
     BOOLEAN bIndexSpecified;
     ULONG ulNextEntry = 0;
     ULONG ulLastEntry = 0;
-    BOOLEAN bDoCase;
     PFILE_DIRECTORY_INFORMATION pDirInfo;
     PFILE_FULL_DIR_INFORMATION pFullDirInfo;
     PFILE_BOTH_DIR_INFORMATION pBothDirInfo;
@@ -144,12 +137,11 @@ AFSQueryDirectory( IN PIRP Irp)
     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;
+    BOOLEAN     bNonWildcardMatch = FALSE;
 
     __Enter
     {
@@ -165,7 +157,7 @@ AFSQueryDirectory( IN PIRP Irp)
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryDirectory Attempted access (%08lX) when pFcb == NULL\n",
+                          "AFSQueryDirectory Attempted access (%p) when pFcb == NULL\n",
                           Irp);
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
@@ -178,7 +170,7 @@ AFSQueryDirectory( IN PIRP Irp)
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSQueryDirectory Attempted access (%08lX) to non-directory Fcb %08lX NodeType %u\n",
+                          "AFSQueryDirectory Attempted access (%p) to non-directory Fcb %p NodeType %u\n",
                           Irp,
                           pFcb,
                           pFcb->Header.NodeTypeCode);
@@ -206,7 +198,48 @@ 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));
+
+        //
+        // Check if we previously processed a direct query
+        //
+
+        if( bInitialQuery &&
+            BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY))
+        {
+
+            bInitialQuery = FALSE;
+        }
+        else if( bRestartScan)
+        {
+            //
+            // Clear our direct to service flag so we reprocess things correctly.
+            //
+
+            ClearFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ Restart Query\n",
+                          &pCcb->DirectoryCB->NameInformation.FileName,
+                          &pCcb->MaskName);
+
+            if( pCcb->MaskName.Length > 0 &&
+                !FsRtlDoesNameContainWildCards( &pCcb->MaskName))
+            {
+
+                if( RtlCompareUnicodeString( &AFSPIOCtlName,
+                                             &pCcb->MaskName,
+                                             TRUE) != 0)
+                {
+                    bNonWildcardMatch = TRUE;
+                }
+            }
+        }
+
+        //
+        // Setup the query mask
+        //
 
         if( bInitialQuery)
         {
@@ -218,7 +251,7 @@ AFSQueryDirectory( IN PIRP Irp)
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSQueryDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
+                          "AFSQueryDirectory Acquiring Dcb lock %p EXCL %08lX\n",
                           &pFcb->NPFcb->Resource,
                           PsGetCurrentThread());
 
@@ -226,6 +259,118 @@ AFSQueryDirectory( IN PIRP Irp)
                             TRUE);
 
             bReleaseFcb = TRUE;
+
+            //
+            // Determine the type of mask passed in for later processing
+            //
+
+            ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
+
+            // build mask if none
+            if( puniArgFileName == NULL)
+            {
+                puniArgFileName = &uniTmpMaskName;
+                puniArgFileName->Length = 0;
+                puniArgFileName->Buffer = NULL;
+            }
+
+            if( puniArgFileName->Length == 0)
+            {
+
+                puniArgFileName->Length = sizeof(WCHAR);
+                puniArgFileName->MaximumLength = (USHORT)4;
+            }
+
+            if( puniArgFileName->Buffer == NULL)
+            {
+
+                puniArgFileName->Buffer = wchMaskBuffer;
+
+                RtlZeroMemory( wchMaskBuffer,
+                               4);
+
+                RtlCopyMemory( &puniArgFileName->Buffer[ 0],
+                               L"*",
+                               sizeof(WCHAR));
+            }
+
+            if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
+                 ( puniArgFileName->Buffer[0] == L'*')))
+            {
+
+                SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
+            }
+            else
+            {
+
+                if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
+                     ( puniArgFileName->Buffer[0] == L'<')) ||
+                    (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
+                    ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
+                {
+
+                    SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
+                }
+
+                //
+                // Build the name for procesisng
+                //
+
+                pCcb->MaskName.Length = puniArgFileName->Length;
+                pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
+
+                pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
+                                                                           pCcb->MaskName.Length,
+                                                                           AFS_GENERIC_MEMORY_6_TAG);
+
+                if( pCcb->MaskName.Buffer == NULL)
+                {
+
+                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+                }
+
+                if( FsRtlDoesNameContainWildCards( puniArgFileName))
+                {
+
+                    RtlUpcaseUnicodeString( &pCcb->MaskName,
+                                            puniArgFileName,
+                                            FALSE);
+
+                    SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
+
+                    if( FsRtlIsNameInExpression( &pCcb->MaskName,
+                                                 &AFSPIOCtlName,
+                                                 TRUE,
+                                                 NULL))
+                    {
+                        SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
+                    }
+                }
+                else
+                {
+
+                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                  AFS_TRACE_LEVEL_VERBOSE,
+                                  "AFSQueryDirectory FsRtlDoesNameContainWildCards == FALSE parent %wZ Mask %wZ\n",
+                                  &pCcb->DirectoryCB->NameInformation.FileName,
+                                  puniArgFileName);
+
+                    RtlCopyMemory( pCcb->MaskName.Buffer,
+                                   puniArgFileName->Buffer,
+                                   pCcb->MaskName.Length);
+
+                    if( RtlCompareUnicodeString( &AFSPIOCtlName,
+                                                 &pCcb->MaskName,
+                                                 TRUE) == 0)
+                    {
+                        SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
+                    }
+                    else
+                    {
+                        bNonWildcardMatch = TRUE;
+                    }
+                }
+            }
         }
         else
         {
@@ -237,7 +382,7 @@ AFSQueryDirectory( IN PIRP Irp)
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
-                          "AFSQueryDirectory Acquiring Dcb lock %08lX SHARED %08lX\n",
+                          "AFSQueryDirectory Acquiring Dcb lock %p SHARED %08lX\n",
                           &pFcb->NPFcb->Resource,
                           PsGetCurrentThread());
 
@@ -245,6 +390,15 @@ AFSQueryDirectory( IN PIRP Irp)
                               TRUE);
 
             bReleaseFcb = TRUE;
+
+            //
+            // Have we already processed this entry directly from the service?
+            //
+
+            if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY))
+            {
+                try_return( ntStatus = STATUS_NO_MORE_FILES);
+            }
         }
 
         //
@@ -258,10 +412,69 @@ AFSQueryDirectory( IN PIRP Irp)
         bReleaseMain = TRUE;
 
         //
-        // Before attempting to insert the new entry, check if we need to validate the parent
+        // Before attempting to insert the new entry, check if we need to enumerate or validate the parent
         //
 
-        if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
+        if( !BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
+        {
+
+            //
+            // If this is a non wildcard match then just process it directly from the service since the directory
+            // is not yet enumerated
+            //
+
+            if( bNonWildcardMatch)
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSQueryDirectory Processing non-wildcard match directly parent %wZ Mask %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+                              &pCcb->DirectoryCB->NameInformation.FileName,
+                              &pCcb->MaskName,
+                              pFcb->ObjectInformation->FileId.Cell,
+                              pFcb->ObjectInformation->FileId.Volume,
+                              pFcb->ObjectInformation->FileId.Vnode,
+                              pFcb->ObjectInformation->FileId.Unique);
+
+                ntStatus = AFSProcessDirectoryQueryDirect( pFcb,
+                                                           pCcb,
+                                                           Irp);
+
+                SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY);
+
+                try_return( ntStatus);
+            }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryDirectory Enumerating 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 = AFSEnumerateDirectory( &pCcb->AuthGroup,
+                                              pFcb->ObjectInformation,
+                                              TRUE);
+
+            if( !NT_SUCCESS( ntStatus))
+            {
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSQueryDirectory Failed to enumerate 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);
+            }
+        }
+        else if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
         {
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
@@ -296,10 +509,15 @@ AFSQueryDirectory( IN PIRP Irp)
             // Perform a new snapshot of the directory
             //
 
+            AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
+                            TRUE);
+
             ntStatus = AFSSnapshotDirectory( pFcb,
                                              pCcb,
                                              FALSE);
 
+            AFSReleaseResource( &pCcb->NPCcb->CcbLock);
+
             if( !NT_SUCCESS( ntStatus))
             {
 
@@ -337,6 +555,9 @@ AFSQueryDirectory( IN PIRP Irp)
             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
         }
 
+        AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
+                        TRUE);
+
         // Check if initial on this map
         if( bInitialQuery)
         {
@@ -348,6 +569,8 @@ AFSQueryDirectory( IN PIRP Irp)
             if( !NT_SUCCESS( ntStatus))
             {
 
+                AFSReleaseResource( &pCcb->NPCcb->CcbLock);
+
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
                               "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
@@ -358,153 +581,60 @@ AFSQueryDirectory( IN PIRP Irp)
                 try_return( ntStatus);
             }
 
-            SetFlag( pCcb->Flags, CCB_FLAGS_DIRECTORY_QUERY_MAPPED);
-
-            ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
-
-            // build mask if none
-            if( puniArgFileName == NULL)
-            {
-                puniArgFileName = &uniTmpMaskName;
-                puniArgFileName->Length = 0;
-                puniArgFileName->Buffer = NULL;
-            }
-
-            if( puniArgFileName->Length == 0)
-            {
-
-                puniArgFileName->Length = sizeof(WCHAR);
-                puniArgFileName->MaximumLength = (USHORT)4;
-            }
+            SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
 
-            if( puniArgFileName->Buffer == NULL)
+            if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
             {
-
-                puniArgFileName->Buffer = wchMaskBuffer;
-
-                RtlZeroMemory( wchMaskBuffer,
-                               4);
-
-                RtlCopyMemory( &puniArgFileName->Buffer[ 0],
-                               L"*",
-                               sizeof(WCHAR));
-            }
-
-            if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
-                 ( puniArgFileName->Buffer[0] == L'*')))
-            {
-
-                SetFlag( pCcb->Flags, CCB_FLAG_FULL_DIRECTORY_QUERY);
-            }
-            else
-            {
-
-                if( (( puniArgFileName->Length == sizeof(WCHAR)) &&
-                     ( puniArgFileName->Buffer[0] == L'<')) ||
-                    (( puniArgFileName->Length == 2*sizeof(WCHAR)) &&
-                    ( RtlEqualMemory( puniArgFileName->Buffer, L"*.", 2*sizeof(WCHAR) ))))
+                if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
                 {
 
-                    SetFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
-                }
+                    AFSReleaseResource( &pCcb->NPCcb->CcbLock);
 
-                //
-                // Build the name for procesisng
-                //
+                    AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
-                pCcb->MaskName.Length = puniArgFileName->Length;
-                pCcb->MaskName.MaximumLength = pCcb->MaskName.Length;
+                    bReleaseMain = FALSE;
 
-                pCcb->MaskName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
-                                                                           pCcb->MaskName.Length,
-                                                                           AFS_GENERIC_MEMORY_6_TAG);
+                    AFSAcquireExcl( &pFcb->NPFcb->Resource,
+                                    TRUE);
 
-                if( pCcb->MaskName.Buffer == NULL)
-                {
-
-                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
-                }
-
-                if( FsRtlDoesNameContainWildCards( puniArgFileName))
-                {
-
-                    RtlUpcaseUnicodeString( &pCcb->MaskName,
-                                            puniArgFileName,
-                                            FALSE);
-
-                    SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS);
-
-                    if( FsRtlIsNameInExpression( &pCcb->MaskName,
-                                                 &AFSPIOCtlName,
-                                                 TRUE,
-                                                 NULL))
-                    {
-                        SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
-                    }
-                }
-                else
-                {
-
-                    RtlCopyMemory( pCcb->MaskName.Buffer,
-                                   puniArgFileName->Buffer,
-                                   pCcb->MaskName.Length);
-
-                    if( RtlCompareUnicodeString( &AFSPIOCtlName,
-                                                 &pCcb->MaskName,
-                                                 TRUE) == 0)
-                    {
-                        SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY);
-                    }
-                }
-
-                if( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY))
-                {
                     if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
                     {
 
-                        AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
-
-                        bReleaseMain = FALSE;
+                        ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
 
-                        AFSAcquireExcl( &pFcb->NPFcb->Resource,
-                                        TRUE);
-
-                        if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
+                        if( !NT_SUCCESS( ntStatus))
                         {
 
-                            ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
-
-                            if( !NT_SUCCESS( ntStatus))
-                            {
-
-                                AFSReleaseResource( &pFcb->NPFcb->Resource);
+                            AFSReleaseResource( &pFcb->NPFcb->Resource);
 
-                                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                              AFS_TRACE_LEVEL_ERROR,
-                                              "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
-                                              &pCcb->DirectoryCB->NameInformation.FileName,
-                                              &pCcb->MaskName,
-                                              ntStatus);
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_ERROR,
+                                          "AFSQueryDirectory Init PIOCtl directory failure for parent %wZ Mask %wZ Status %08lX\n",
+                                          &pCcb->DirectoryCB->NameInformation.FileName,
+                                          &pCcb->MaskName,
+                                          ntStatus);
 
-                                try_return( ntStatus);
-                            }
+                            try_return( ntStatus);
                         }
+                    }
 
-                        AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                                          TRUE);
+                    AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                                        TRUE);
 
-                        bReleaseMain = TRUE;
+                    bReleaseMain = TRUE;
 
-                        AFSReleaseResource( &pFcb->NPFcb->Resource);
-                    }
-                }
+                    AFSReleaseResource( &pFcb->NPFcb->Resource);
 
-                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                              AFS_TRACE_LEVEL_VERBOSE,
-                              "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
-                              &pCcb->DirectoryCB->NameInformation.FileName,
-                              &pCcb->MaskName);
+                    AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
+                                    TRUE);
+                }
             }
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryDirectory Enumerating content for parent %wZ Mask %wZ\n",
+                          &pCcb->DirectoryCB->NameInformation.FileName,
+                          &pCcb->MaskName);
         }
 
         // Check if we need to start from index
@@ -538,6 +668,12 @@ AFSQueryDirectory( IN PIRP Irp)
             }
         }
 
+        AFSReleaseResource( &pCcb->NPCcb->CcbLock);
+
+        AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+        bReleaseMain = FALSE;
+
         switch( FileInformationClass)
         {
 
@@ -583,22 +719,42 @@ AFSQueryDirectory( IN PIRP Irp)
 
                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                               AFS_TRACE_LEVEL_ERROR,
-                              "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
+                              "AFSQueryDirectory (%p) Unknown FileInformationClass %u\n",
                               Irp,
                               FileInformationClass);
 
                 try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
         }
 
-        AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
-
-        bReleaseMain = FALSE;
-
         while( TRUE)
         {
 
             ULONG ulBytesRemainingInBuffer;
-            int rc;
+
+            //
+            // Drop the DirOpenReferenceCount held during a prior
+            // execution of the loop
+            //
+
+            if ( pDirEntry != NULL)
+            {
+
+                lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                              AFS_TRACE_LEVEL_VERBOSE,
+                              "AFSQueryDirectory Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
+                              &pDirEntry->NameInformation.FileName,
+                              pDirEntry,
+                              pCcb,
+                              lCount);
+
+                ASSERT( lCount >= 0);
+
+                pDirEntry = NULL;
+            }
+
+            ulAdditionalAttributes = 0;
 
             //
             //  If the user had requested only a single match and we have
@@ -611,6 +767,10 @@ AFSQueryDirectory( IN PIRP Irp)
                 try_return( ntStatus);
             }
 
+            //
+            // On Success, pDirEntry has a held DirOpenReferenceCount
+            //
+
             pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
                                                pCcb);
 
@@ -643,8 +803,6 @@ AFSQueryDirectory( IN PIRP Irp)
                      BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
             {
 
-                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
                 continue;
             }
 
@@ -667,8 +825,6 @@ AFSQueryDirectory( IN PIRP Irp)
                     if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
                     {
 
-                        lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
                         continue;
                     }
                 }
@@ -688,8 +844,6 @@ AFSQueryDirectory( IN PIRP Irp)
                                                       NULL))
                         {
 
-                            lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
                             continue;
                         }
                     }
@@ -710,8 +864,6 @@ AFSQueryDirectory( IN PIRP Irp)
                                                          TRUE))
                             {
 
-                                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
                                 continue;
                             }
                         }
@@ -724,74 +876,134 @@ AFSQueryDirectory( IN PIRP Irp)
             // We don't worry about entries while enumerating the directory
             //
 
-            AFSValidateEntry( pDirEntry,
-                              &pCcb->AuthGroup,
-                              FALSE);
+            if ( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
+            {
+
+                ntStatus = AFSValidateEntry( pDirEntry,
+                                             &pCcb->AuthGroup,
+                                             FALSE,
+                                             FALSE);
+                if ( NT_SUCCESS( ntStatus))
+                {
+
+                    ClearFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                }
+                else
+                {
+
+                    ntStatus = STATUS_SUCCESS;
+                }
+            }
 
             pObjectInfo = pDirEntry->ObjectInformation;
 
-            bUseFileInfo = FALSE;
+            //  Here are the rules concerning filling up the buffer:
+            //
+            //  1.  The Io system guarantees that there will always be
+            //      enough room for at least one base record.
+            //
+            //  2.  If the full first record (including file name) cannot
+            //      fit, as much of the name as possible is copied and
+            //      STATUS_BUFFER_OVERFLOW is returned.
+            //
+            //  3.  If a subsequent record cannot completely fit into the
+            //      buffer, none of it (as in 0 bytes) is copied, and
+            //      STATUS_SUCCESS is returned.  A subsequent query will
+            //      pick up with this record.
 
-            ulAdditionalAttributes = 0;
+            ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
 
-            if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
+            if( ( ulNextEntry != 0) &&
+                ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
+                  ( ulUserBufferLength < ulNextEntry) ) )
             {
 
                 //
-                // Go grab the file information for this entry
-                // No worries on failures since we will just display
-                // pseudo information
+                // Back off our current index
                 //
 
-                RtlZeroMemory( &stFileInfo,
-                               sizeof( AFSFileInfoCB));
+                pCcb->CurrentDirIndex--;
+
+                try_return( ntStatus = STATUS_SUCCESS);
+            }
+
+
+            switch ( FileInformationClass)
+            {
+            case FileIdBothDirectoryInformation:
+            case FileBothDirectoryInformation:
+            case FileIdFullDirectoryInformation:
+            case FileFullDirectoryInformation:
+            case FileDirectoryInformation:
+
+                //
+                // For Symlinks and Mount Points the reparse point attribute
+                // must be associated with the directory entry.  In addition,
+                // for Symlinks it must be determined if the target object is
+                // a directory or not.  If so, the directory attribute must be
+                // specified.  Mount points always refer to directories and
+                // must have the directory attribute set.
+                //
 
-                if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
-                                                           pDirEntry,
-                                                           &pCcb->FullFileName,
-                                                           pCcb->NameArray,
-                                                           &pCcb->AuthGroup,
-                                                           &stFileInfo)))
+                switch( pObjectInfo->FileType)
                 {
 
-                    ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
+                case AFS_FILE_TYPE_MOUNTPOINT:
+                case AFS_FILE_TYPE_DFSLINK:
+                    {
+
+                        ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
+
+                        break;
+                    }
+
+                case AFS_FILE_TYPE_SYMLINK:
+                    {
+
+                        //
+                        // Go grab the file information for this entry
+                        // No worries on failures since we will just display
+                        // pseudo information
+                        //
+
+                        RtlZeroMemory( &stFileInfo,
+                                       sizeof( AFSFileInfoCB));
+
+                        if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
+                                                                   pDirEntry,
+                                                                   &pCcb->FullFileName,
+                                                                   pCcb->NameArray,
+                                                                   &pCcb->AuthGroup,
+                                                                   &stFileInfo)))
+                        {
+
+                            if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                            {
+
+                                ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY;
+                            }
+                        }
+
+                        ulAdditionalAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
 
-                    bUseFileInfo = TRUE;
+                        break;
+                    }
                 }
             }
 
-            //  Here are the rules concerning filling up the buffer:
             //
-            //  1.  The Io system guarantees that there will always be
-            //      enough room for at least one base record.
-            //
-            //  2.  If the full first record (including file name) cannot
-            //      fit, as much of the name as possible is copied and
-            //      STATUS_BUFFER_OVERFLOW is returned.
+            // Check if the name begins with a . and we are hiding them
             //
-            //  3.  If a subsequent record cannot completely fit into the
-            //      buffer, none of it (as in 0 bytes) is copied, and
-            //      STATUS_SUCCESS is returned.  A subsequent query will
-            //      pick up with this record.
-
-            ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
 
-            if( ( ulNextEntry != 0) &&
-                ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
-                  ( ulUserBufferLength < ulNextEntry) ) )
+            if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
+                pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
+                BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
             {
 
-                //
-                // Back off our current index
-                //
-
-                pCcb->CurrentDirIndex--;
-
-                lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
-                try_return( ntStatus = STATUS_SUCCESS);
+                ulAdditionalAttributes |= FILE_ATTRIBUTE_HIDDEN;
             }
 
+
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_VERBOSE,
                           "AFSQueryDirectory Insert into parent %wZ Entry %wZ\n",
@@ -830,20 +1042,7 @@ AFSQueryDirectory( IN PIRP Irp)
                 {
                     pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
 
-                    if( bUseFileInfo)
-                    {
-
-                        pDirInfo->CreationTime = stFileInfo.CreationTime;
-                        pDirInfo->LastWriteTime = stFileInfo.LastWriteTime;
-                        pDirInfo->LastAccessTime = stFileInfo.LastAccessTime;
-                        pDirInfo->ChangeTime = stFileInfo.ChangeTime;
-
-                        pDirInfo->EndOfFile = stFileInfo.EndOfFile;
-                        pDirInfo->AllocationSize = stFileInfo.AllocationSize;
-
-                        pDirInfo->FileAttributes = stFileInfo.FileAttributes | ulAdditionalAttributes;
-                    }
-                    else if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
+                    if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
                     {
 
                         pDirInfo->CreationTime = pFcb->ObjectInformation->CreationTime;
@@ -874,19 +1073,16 @@ AFSQueryDirectory( IN PIRP Irp)
                         pDirInfo->EndOfFile = pObjectInfo->EndOfFile;
                         pDirInfo->AllocationSize = pObjectInfo->AllocationSize;
 
-                        pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
-                    }
-
-                    //
-                    // Check if the name begins with a . and we are hiding them
-                    //
+                        if ( ulAdditionalAttributes && pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
+                        {
 
-                    if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
-                        pDirEntry->NameInformation.FileName.Buffer[ 0] == L'.' &&
-                        BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES))
-                    {
+                            pDirInfo->FileAttributes = ulAdditionalAttributes;
+                        }
+                        else
+                        {
 
-                        pDirInfo->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+                            pDirInfo->FileAttributes = pObjectInfo->FileAttributes | ulAdditionalAttributes;
+                        }
                     }
 
                     pDirInfo->FileIndex = pDirEntry->FileIndex;
@@ -903,19 +1099,16 @@ AFSQueryDirectory( IN PIRP Irp)
 
                     break;
                 }
+
                 default:
                 {
                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                   AFS_TRACE_LEVEL_ERROR,
-                                  "AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
+                                  "AFSQueryDirectory (%p) Unknown FileInformationClass %u\n",
                                   Irp,
                                   FileInformationClass);
 
-                    lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
                     try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
-
-                    break;
                 }
             }
 
@@ -939,13 +1132,9 @@ 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
@@ -955,6 +1144,22 @@ AFSQueryDirectory( IN PIRP Irp)
 
 try_exit:
 
+        if ( pDirEntry != NULL)
+        {
+
+            lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSQueryDirectory Decrement8 count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirEntry->NameInformation.FileName,
+                          pDirEntry,
+                          pCcb,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
         if( bReleaseMain)
         {
 
@@ -1003,7 +1208,7 @@ AFSNotifyChangeDirectory( IN PIRP Irp)
 
             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                           AFS_TRACE_LEVEL_ERROR,
-                          "AFSNotifyChangeDirectory Attempted access (%08lX) when pFcb == NULL\n",
+                          "AFSNotifyChangeDirectory Attempted access (%p) when pFcb == NULL\n",
                           Irp);
 
             try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
@@ -1029,7 +1234,7 @@ AFSNotifyChangeDirectory( IN PIRP Irp)
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSNotifyChangeDirectory Acquiring Dcb lock %08lX EXCL %08lX\n",
+                      "AFSNotifyChangeDirectory Acquiring Dcb lock %p EXCL %08lX\n",
                       &pFcb->NPFcb->Resource,
                       PsGetCurrentThread());
 
@@ -1094,6 +1299,12 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
     __Enter
     {
 
+        AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                          TRUE);
+
+        AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+                        TRUE);
+
         //
         // Is this a PIOCtl query
         //
@@ -1107,12 +1318,6 @@ 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",
@@ -1139,12 +1344,6 @@ 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",
@@ -1163,12 +1362,6 @@ 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",
@@ -1203,9 +1396,6 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
             // Get to a valid entry
             //
 
-            AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
-                              TRUE);
-
             while( ulCount < pSnapshotHdr->EntryCount)
             {
 
@@ -1242,8 +1432,6 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
                                       ObjectInfo->FileId.Volume,
                                       ObjectInfo->FileId.Vnode,
                                       ObjectInfo->FileId.Unique);
-
-                        lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
                     }
                     else
                     {
@@ -1276,13 +1464,29 @@ AFSLocateNextDirEntry( IN AFSObjectInfoCB *ObjectInfo,
 
                 Ccb->CurrentDirIndex++;
             }
-
-            AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
 
 try_exit:
 
-        NOTHING;
+        if( pDirEntry != NULL)
+        {
+
+            lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
+                          AFS_TRACE_LEVEL_VERBOSE,
+                          "AFSLocateNextDirEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
+                          &pDirEntry->NameInformation.FileName,
+                          pDirEntry,
+                          Ccb,
+                          lCount);
+
+            ASSERT( lCount >= 0);
+        }
+
+        AFSReleaseResource( &Ccb->NPCcb->CcbLock);
+
+        AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
     }
 
     return pDirEntry;
@@ -1303,6 +1507,9 @@ AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
     __Enter
     {
 
+        AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+                        TRUE);
+
         Ccb->CurrentDirIndex = DirIndex;
 
         if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
@@ -1374,7 +1581,7 @@ AFSLocateDirEntryByIndex( IN AFSObjectInfoCB *ObjectInfo,
 
 try_exit:
 
-        NOTHING;
+        AFSReleaseResource( &Ccb->NPCcb->CcbLock);
     }
 
     return pDirEntry;
@@ -1423,7 +1630,7 @@ AFSSnapshotDirectory( IN AFSFcb *Fcb,
             if( Ccb->DirectorySnapshot != NULL)
             {
 
-                AFSExFreePool( Ccb->DirectorySnapshot);
+                AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
 
                 Ccb->DirectorySnapshot = NULL;
             }
@@ -1511,7 +1718,7 @@ AFSSnapshotDirectory( IN AFSFcb *Fcb,
         if( Ccb->DirectorySnapshot != NULL)
         {
 
-            AFSExFreePool( Ccb->DirectorySnapshot);
+            AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
 
             Ccb->DirectorySnapshot = NULL;
         }
@@ -1541,6 +1748,9 @@ AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
     __Enter
     {
 
+        AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+                        TRUE);
+
         //
         // Build a dir name based on the FID of the file
         //
@@ -1590,7 +1800,7 @@ AFSFsRtlNotifyFullChangeDirectory( IN AFSObjectInfoCB *ObjectInfo,
 
         AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NOTIF_PROCESSING,
                       AFS_TRACE_LEVEL_VERBOSE,
-                      "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %08lX Filter %08lX Tree %02lX\n",
+                      "AFSFsRtlNotifyFullChangeDirectory Registering notification on %wZ Irp %p Filter %08lX Tree %02lX\n",
                       &Ccb->NotifyMask,
                       NotifyIrp,
                       CompletionFilter,
@@ -1616,11 +1826,13 @@ try_exit:
             if( Ccb->NotifyMask.Buffer != NULL)
             {
 
-                AFSExFreePool( Ccb->NotifyMask.Buffer);
+                AFSExFreePoolWithTag( Ccb->NotifyMask.Buffer, AFS_GENERIC_MEMORY_7_TAG);
 
                 Ccb->NotifyMask.Buffer = NULL;
             }
         }
+
+        AFSReleaseResource( &Ccb->NPCcb->CcbLock);
     }
 
     return ntStatus;
@@ -1735,7 +1947,7 @@ try_exit:
         if( uniName.Buffer != NULL)
         {
 
-            AFSExFreePool( uniName.Buffer);
+            AFSExFreePoolWithTag( uniName.Buffer, AFS_GENERIC_MEMORY_8_TAG);
         }
     }
 
@@ -1750,10 +1962,9 @@ BOOLEAN
 AFSNotifyReportChangeCallback( IN void *NotifyContext,
                                IN void *FilterContext)
 {
-
+    UNREFERENCED_PARAMETER(NotifyContext);
+    UNREFERENCED_PARAMETER(FilterContext);
     BOOLEAN bReturn = TRUE;
-    AFSCcb *pDirCcb = (AFSCcb *)NotifyContext;
-    AFSCcb *pNotifyCcb = (AFSCcb *)FilterContext;
 
     __Enter
     {
@@ -1800,3 +2011,238 @@ AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr,
 
     return bIsInSnapshot;
 }
+
+NTSTATUS
+AFSProcessDirectoryQueryDirect( IN AFSFcb *Fcb,
+                                IN AFSCcb *Ccb,
+                                IN IRP *Irp)
+{
+
+    NTSTATUS        ntStatus = STATUS_SUCCESS;
+    AFSDirEnumEntry *pDirEnum = NULL;
+    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
+    PUCHAR           pBuffer = NULL;
+    ULONG            ulBaseLength = 0;
+    ULONG            ulAdditionalAttributes = 0;
+    ULONG            ulBytesConverted = 0;
+    PFILE_DIRECTORY_INFORMATION pDirInfo;
+    PFILE_FULL_DIR_INFORMATION pFullDirInfo;
+    PFILE_BOTH_DIR_INFORMATION pBothDirInfo;
+    PFILE_NAMES_INFORMATION pNamesInfo;
+
+    __Enter
+    {
+
+        //
+        // query the service for the entry
+        //
+
+        ntStatus = AFSEvaluateTargetByName( &Ccb->AuthGroup,
+                                            Fcb->ObjectInformation,
+                                            &Ccb->MaskName,
+                                            AFS_REQUEST_FLAG_LAST_COMPONENT,
+                                            &pDirEnum);
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                          AFS_TRACE_LEVEL_ERROR,
+                          "AFSProcessDirectoryQueryDirect Failed to locate non-wildcard match directly parent %wZ Mask %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+                          &Ccb->DirectoryCB->NameInformation.FileName,
+                          &Ccb->MaskName,
+                          Fcb->ObjectInformation->FileId.Cell,
+                          Fcb->ObjectInformation->FileId.Volume,
+                          Fcb->ObjectInformation->FileId.Vnode,
+                          Fcb->ObjectInformation->FileId.Unique,
+                          ntStatus);
+
+            try_return( ntStatus = STATUS_NO_SUCH_FILE);
+        }
+
+        pBuffer = (PUCHAR)AFSLockSystemBuffer( Irp,
+                                               pIrpSp->Parameters.QueryDirectory.Length);
+
+        if( pBuffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Process the enum request
+        //
+
+        switch( pIrpSp->Parameters.QueryDirectory.FileInformationClass)
+        {
+
+            case FileDirectoryInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_DIRECTORY_INFORMATION,
+                                             FileName[0] );
+                break;
+
+            case FileFullDirectoryInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION,
+                                             FileName[0] );
+                break;
+
+            case FileNamesInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
+                                             FileName[0] );
+                break;
+
+            case FileBothDirectoryInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION,
+                                             FileName[0] );
+                break;
+
+            case FileIdBothDirectoryInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION,
+                                             FileName[0] );
+
+                break;
+
+            case FileIdFullDirectoryInformation:
+
+                ulBaseLength = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION,
+                                             FileName[0] );
+
+                break;
+
+            default:
+
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessDirectoryQueryDirect (%p) Unknown FileInformationClass %u\n",
+                              Irp,
+                              pIrpSp->Parameters.QueryDirectory.FileInformationClass);
+
+                try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
+        }
+
+        switch( pDirEnum->FileType)
+        {
+
+            case AFS_FILE_TYPE_MOUNTPOINT:
+            case AFS_FILE_TYPE_DFSLINK:
+            {
+
+                ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
+
+                break;
+            }
+
+            case AFS_FILE_TYPE_SYMLINK:
+            {
+
+                //
+                // Note: we need to evaluate this entry to determine if the target is a directory or not
+                //
+
+                ulAdditionalAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
+
+                break;
+            }
+        }
+
+        //  Zero the base part of the structure.
+        RtlZeroMemory( pBuffer,
+                       ulBaseLength);
+
+        switch( pIrpSp->Parameters.QueryDirectory.FileInformationClass)
+        {
+
+            //  Now fill the base parts of the structure that are applicable.
+            case FileIdBothDirectoryInformation:
+            case FileBothDirectoryInformation:
+            {
+                pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)pBuffer;
+
+                pBothDirInfo->ShortNameLength = (CHAR)pDirEnum->ShortNameLength;
+
+                if( pDirEnum->ShortNameLength > 0)
+                {
+                    RtlCopyMemory( &pBothDirInfo->ShortName[ 0],
+                                   &pDirEnum->ShortName[ 0],
+                                   pBothDirInfo->ShortNameLength);
+                }
+            }
+            case FileIdFullDirectoryInformation:
+            case FileFullDirectoryInformation:
+            {
+                pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)pBuffer;
+                pFullDirInfo->EaSize = 0;
+            }
+            case FileDirectoryInformation:
+            {
+                pDirInfo = (PFILE_DIRECTORY_INFORMATION)pBuffer;
+
+                pDirInfo->CreationTime = pDirEnum->CreationTime;
+                pDirInfo->LastWriteTime = pDirEnum->LastWriteTime;
+                pDirInfo->LastAccessTime = pDirEnum->LastAccessTime;
+                pDirInfo->ChangeTime = pDirEnum->ChangeTime;
+
+                pDirInfo->EndOfFile = pDirEnum->EndOfFile;
+                pDirInfo->AllocationSize = pDirEnum->AllocationSize;
+
+                if ( ulAdditionalAttributes && pDirEnum->FileAttributes == FILE_ATTRIBUTE_NORMAL)
+                {
+                    pDirInfo->FileAttributes = ulAdditionalAttributes;
+                }
+                else
+                {
+                    pDirInfo->FileAttributes = pDirEnum->FileAttributes | ulAdditionalAttributes;
+                }
+
+                pDirInfo->FileIndex = pDirEnum->FileIndex;
+                pDirInfo->FileNameLength = pDirEnum->FileNameLength;
+
+                break;
+            }
+
+            case FileNamesInformation:
+            {
+                pNamesInfo = (PFILE_NAMES_INFORMATION)pBuffer;
+                pNamesInfo->FileIndex = pDirEnum->FileIndex;
+                pNamesInfo->FileNameLength = pDirEnum->FileNameLength;
+
+                break;
+            }
+
+            default:
+            {
+                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                              AFS_TRACE_LEVEL_ERROR,
+                              "AFSProcessDirectoryQueryDirect (%p) Unknown FileInformationClass %u\n",
+                              Irp,
+                              pIrpSp->Parameters.QueryDirectory.FileInformationClass);
+
+                try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
+            }
+        }
+
+        ulBytesConverted = pIrpSp->Parameters.QueryDirectory.Length - ulBaseLength >= pDirEnum->FileNameLength ?
+                                        pDirEnum->FileNameLength :
+                                        pIrpSp->Parameters.QueryDirectory.Length - ulBaseLength;
+
+        RtlCopyMemory( &pBuffer[ ulBaseLength],
+                       (void *)((char *)pDirEnum + pDirEnum->FileNameOffset),
+                       ulBytesConverted);
+
+        Irp->IoStatus.Information = ulBaseLength + ulBytesConverted;
+
+try_exit:
+
+        if( pDirEnum != NULL)
+        {
+            ExFreePool( pDirEnum);
+        }
+    }
+
+    return ntStatus;
+}