From b7ba97ad537bd0e9a241f052ddd1c3a50c74745b Mon Sep 17 00:00:00 2001 From: Peter Scott Date: Fri, 15 Feb 2013 08:44:06 -0500 Subject: [PATCH] Windows: Permit direct to service non-wildcard lookups The AFS redirector has required that directories be fully enumerated when the directory object is opened. This is a very expensive operation involving large numbers of file server RPC round trips for directories with tens of thousands of objects and those containing symlinks. This patchset delays directory enumeration for the last component in a path until such time as dirctory data is requested by the application. If the request is for a non-wildcard pattern, the service will be asked to provide the details for just the one required object. Delaying the directory enumeration improves performance for GetFileAttributes[Ex], GetDiskFreeSpace[Ex], GetVolumeInformation, and GetNamedSecurityInfo Win32 API calls. In those cases it is no longer necessary to enumerate the target directory at all. Change-Id: I7ef2fbafff925697d8b40e56837ef53bfcc78542 Reviewed-on: http://gerrit.openafs.org/9118 Reviewed-by: Peter Scott Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp | 618 ++++++++++++++---- .../afsrdr/kernel/lib/AFSNameSupport.cpp | 3 +- .../afsrdr/kernel/lib/Include/AFSCommon.h | 5 + .../afsrdr/kernel/lib/Include/AFSDefines.h | 1 + 4 files changed, 490 insertions(+), 137 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp b/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp index b6bb2ef76..5fd860d4c 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSDirControl.cpp @@ -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 @@ -10,10 +10,8 @@ * - 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 @@ -143,6 +141,7 @@ AFSQueryDirectory( IN PIRP Irp) AFSObjectInfoCB *pObjectInfo = NULL; ULONG ulAdditionalAttributes = 0; LONG lCount; + BOOLEAN bNonWildcardMatch = FALSE; __Enter { @@ -201,6 +200,39 @@ AFSQueryDirectory( IN PIRP Irp) 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); + + if( !FsRtlDoesNameContainWildCards( &pCcb->MaskName)) + { + + if( RtlCompareUnicodeString( &AFSPIOCtlName, + &pCcb->MaskName, + TRUE) != 0) + { + bNonWildcardMatch = TRUE; + } + } + } + + // + // Setup the query mask + // + if( bInitialQuery) { @@ -219,6 +251,112 @@ 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 + { + + 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 { @@ -238,6 +376,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); + } } // @@ -251,10 +398,71 @@ 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); + } + + SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED); + } + else if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY)) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, @@ -363,156 +571,58 @@ AFSQueryDirectory( IN PIRP Irp) SetFlag( pCcb->Flags, CCB_FLAG_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; - } - - 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( BooleanFlagOn( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY)) { - - 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) + if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL) { - try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); - } + AFSReleaseResource( &pCcb->NPCcb->CcbLock); - if( FsRtlDoesNameContainWildCards( puniArgFileName)) - { + AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock); - RtlUpcaseUnicodeString( &pCcb->MaskName, - puniArgFileName, - FALSE); - - SetFlag( pCcb->Flags, CCB_FLAG_MASK_CONTAINS_WILD_CARDS); + bReleaseMain = FALSE; - if( FsRtlIsNameInExpression( &pCcb->MaskName, - &AFSPIOCtlName, - TRUE, - NULL)) - { - SetFlag( pCcb->Flags, CCB_FLAG_MASK_PIOCTL_QUERY); - } - } - else - { + AFSAcquireExcl( &pFcb->NPFcb->Resource, + TRUE); - 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( &pCcb->NPCcb->CcbLock); - - 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); - AFSAcquireExcl( &pCcb->NPCcb->CcbLock, - TRUE); - } + 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); } + + 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 @@ -1880,3 +1990,239 @@ 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; + AFSFileInfoCB stFileInfo; + 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; +} diff --git a/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp b/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp index 24e9357b6..cba608bc7 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp @@ -1173,7 +1173,8 @@ AFSLocateNameEntry( IN GUID *AuthGroup, // if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY && - !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED)) + !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) && + uniPathName.Length > 0) { AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING, diff --git a/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h b/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h index 50735637e..2c137fa28 100644 --- a/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h +++ b/src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h @@ -992,6 +992,11 @@ BOOLEAN AFSIsNameInSnapshot( IN AFSSnapshotHdr *SnapshotHdr, IN ULONG HashIndex); +NTSTATUS +AFSProcessDirectoryQueryDirect( IN AFSFcb *Fcb, + IN AFSCcb *Ccb, + IN IRP *Irp); + // // AFSFSControl.cpp Prototypes // diff --git a/src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h b/src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h index 387b5a7e5..b0b0a305e 100644 --- a/src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h +++ b/src/WINNT/afsrdr/kernel/lib/Include/AFSDefines.h @@ -264,6 +264,7 @@ NTSTATUS #define CCB_FLAG_MASK_PIOCTL_QUERY 0x00000040 #define CCB_FLAG_MASK_OPENED_REPARSE_POINT 0x00000080 #define CCB_FLAG_INSERTED_CCB_LIST 0x00000100 +#define CCB_FLAG_DIRECTORY_QUERY_DIRECT_QUERY 0x00000200 // // DirEntry flags -- 2.39.5