/*
- * 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
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
{
break;
}
}
- __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+ __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
{
AFSDbgLogMsg( 0,
0,
"EXCEPTION - AFSDirControl\n");
+
+ AFSDumpTraceFilesFnc();
}
if( ntStatus != STATUS_PENDING)
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;
ULONG ulBytesConverted;
AFSDirectoryCB *pDirEntry = NULL;
BOOLEAN bReleaseMain = FALSE;
- ULONG ulTargetFileType = AFS_FILE_TYPE_UNKNOWN;
+ BOOLEAN bReleaseFcb = FALSE;
AFSFileInfoCB stFileInfo;
- BOOLEAN bUseFileInfo = TRUE;
AFSObjectInfoCB *pObjectInfo = NULL;
ULONG ulAdditionalAttributes = 0;
+ LONG lCount;
+ BOOLEAN bNonWildcardMatch = FALSE;
__Enter
{
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);
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);
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)
{
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());
AFSAcquireExcl( &pFcb->NPFcb->Resource,
TRUE);
+ bReleaseFcb = TRUE;
+
//
- // Tell the service to prime the cache of the directory content
+ // Determine the type of mask passed in for later processing
//
- ntStatus = AFSEnumerateDirectoryNoResponse( &pFcb->AuthGroup,
- &pFcb->ObjectInformation->FileId);
+ ClearFlag( pCcb->Flags, CCB_FLAG_DIR_OF_DIRS_ONLY);
- if( !NT_SUCCESS( ntStatus))
+ // build mask if none
+ if( puniArgFileName == NULL)
{
+ puniArgFileName = &uniTmpMaskName;
+ puniArgFileName->Length = 0;
+ puniArgFileName->Buffer = NULL;
+ }
- AFSReleaseResource( &pFcb->NPFcb->Resource);
+ if( puniArgFileName->Length == 0)
+ {
- 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);
+ puniArgFileName->Length = sizeof(WCHAR);
+ puniArgFileName->MaximumLength = (USHORT)4;
+ }
- try_return( ntStatus);
+ 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
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());
AFSAcquireShared( &pFcb->NPFcb->Resource,
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);
+ }
}
//
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,
pFcb->ObjectInformation->FileId.Vnode,
pFcb->ObjectInformation->FileId.Unique);
- ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
+ ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
pCcb->DirectoryCB);
if( !NT_SUCCESS( ntStatus))
// 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))
{
AFSReleaseResource( &pFcb->NPFcb->Resource);
+ bReleaseFcb = FALSE;
+
//
// Start processing the data
//
try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
}
+ AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
+ TRUE);
+
// Check if initial on this map
if( bInitialQuery)
{
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",
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)
- {
+ SetFlag( pCcb->Flags, CCB_FLAG_DIRECTORY_QUERY_MAPPED);
- puniArgFileName->Length = sizeof(WCHAR);
- puniArgFileName->MaximumLength = (USHORT)4;
- }
-
- 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;
-
- AFSAcquireExcl( &pFcb->NPFcb->Resource,
- TRUE);
+ ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
- if( pFcb->ObjectInformation->Specific.Directory.PIOCtlDirectoryCB == NULL)
+ if( !NT_SUCCESS( ntStatus))
{
- ntStatus = AFSInitPIOCtlDirectoryCB( pFcb->ObjectInformation);
+ AFSReleaseResource( &pFcb->NPFcb->Resource);
- if( !NT_SUCCESS( ntStatus))
- {
-
- 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);
}
-
- 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
}
}
+ AFSReleaseResource( &pCcb->NPCcb->CcbLock);
+
+ AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+ bReleaseMain = FALSE;
+
switch( FileInformationClass)
{
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
try_return( ntStatus);
}
+ //
+ // On Success, pDirEntry has a held DirOpenReferenceCount
+ //
+
pDirEntry = AFSLocateNextDirEntry( pFcb->ObjectInformation,
pCcb);
BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
{
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
continue;
}
if( !FlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
{
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
continue;
}
}
NULL))
{
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
continue;
}
}
TRUE))
{
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
continue;
}
}
// We don't worry about entries while enumerating the directory
//
- AFSValidateEntry( pDirEntry,
- &pFcb->AuthGroup,
- FALSE,
- 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.
+
+ ulBytesRemainingInBuffer = ulUserBufferLength - ulNextEntry;
+
+ if( ( ulNextEntry != 0) &&
+ ( ( ulBaseLength + pDirEntry->NameInformation.FileName.Length > ulBytesRemainingInBuffer) ||
+ ( ulUserBufferLength < ulNextEntry) ) )
+ {
+
+ //
+ // Back off our current index
+ //
+
+ 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.
+ //
+
+ switch( pObjectInfo->FileType)
+ {
+
+ case AFS_FILE_TYPE_MOUNTPOINT:
+ case AFS_FILE_TYPE_DFSLINK:
+ {
+
+ ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
- ulAdditionalAttributes = 0;
+ break;
+ }
- if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
- {
+ case AFS_FILE_TYPE_SYMLINK:
+ {
- //
- // Go grab the file information for this entry
- // No worries on failures since we will just display
- // pseudo information
- //
+ //
+ // 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)))
+ {
- RtlZeroMemory( &stFileInfo,
- sizeof( AFSFileInfoCB));
+ if ( stFileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
- if( NT_SUCCESS( AFSRetrieveFileAttributes( pCcb->DirectoryCB,
- pDirEntry,
- &pCcb->FullFileName,
- pCcb->NameArray,
- &stFileInfo)))
- {
+ ulAdditionalAttributes = FILE_ATTRIBUTE_DIRECTORY;
+ }
+ }
- ulAdditionalAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
+ 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--;
-
- 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",
{
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;
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;
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);
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
-
- break;
}
}
if( ulBytesConverted < pDirEntry->NameInformation.FileName.Length)
{
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
try_return( ntStatus = STATUS_BUFFER_OVERFLOW);
}
- InterlockedDecrement( &pDirEntry->OpenReferenceCount);
-
dStatus = STATUS_SUCCESS;
// Set ourselves up for the next iteration
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)
{
AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
}
+ if ( bReleaseFcb)
+ {
+
+ AFSReleaseResource( &pFcb->NPFcb->Resource);
+ }
+
if( pFcb != NULL)
{
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);
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());
AFSSnapshotHdr *pSnapshotHdr = NULL;
AFSSnapshotEntry *pSnapshotEntry = NULL;
ULONG ulCount = 0;
+ LONG lCount;
__Enter
{
+ AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+ TRUE);
+
+ AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+ TRUE);
+
//
// Is this a PIOCtl query
//
// Get to a valid entry
//
- AFSAcquireShared( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
- TRUE);
-
while( ulCount < pSnapshotHdr->EntryCount)
{
ObjectInfo->FileId.Volume,
ObjectInfo->FileId.Vnode,
ObjectInfo->FileId.Unique);
-
- InterlockedIncrement( &pDirEntry->OpenReferenceCount);
}
else
{
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;
__Enter
{
+ AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+ TRUE);
+
Ccb->CurrentDirIndex = DirIndex;
if( DirIndex == (ULONG)AFS_DIR_ENTRY_DOT_INDEX)
try_exit:
- NOTHING;
+ AFSReleaseResource( &Ccb->NPCcb->CcbLock);
}
return pDirEntry;
if( Ccb->DirectorySnapshot != NULL)
{
- AFSExFreePool( Ccb->DirectorySnapshot);
+ AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
Ccb->DirectorySnapshot = NULL;
}
if( Ccb->DirectorySnapshot != NULL)
{
- AFSExFreePool( Ccb->DirectorySnapshot);
+ AFSExFreePoolWithTag( Ccb->DirectorySnapshot, AFS_DIR_SNAPSHOT_TAG);
Ccb->DirectorySnapshot = NULL;
}
__Enter
{
+ AFSAcquireExcl( &Ccb->NPCcb->CcbLock,
+ TRUE);
+
//
// Build a dir name based on the FID of the file
//
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,
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;
if( uniName.Buffer != NULL)
{
- AFSExFreePool( uniName.Buffer);
+ AFSExFreePoolWithTag( uniName.Buffer, AFS_GENERIC_MEMORY_8_TAG);
}
}
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
{
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;
+}