}
//
- // Grab the directory node hdr tree lock shared while parsing the directory
+ // Grab the directory node hdr tree lock while parsing the directory
// contents
//
- AFSAcquireShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
- TRUE);
+ AFSAcquireExcl( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+ TRUE);
bReleaseMain = TRUE;
//
+ // Before attempting to insert the new entry, check if we need to validate the parent
+ //
+
+ if( BooleanFlagOn( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
+ {
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSQueryDirectory Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
+ &pCcb->DirectoryCB->NameInformation.FileName,
+ pFcb->ObjectInformation->FileId.Cell,
+ pFcb->ObjectInformation->FileId.Volume,
+ pFcb->ObjectInformation->FileId.Vnode,
+ pFcb->ObjectInformation->FileId.Unique);
+
+ ntStatus = AFSVerifyEntry( &pFcb->AuthGroup,
+ pCcb->DirectoryCB);
+
+ if( !NT_SUCCESS( ntStatus))
+ {
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSQueryDirectory Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
+ &pCcb->DirectoryCB->NameInformation.FileName,
+ pFcb->ObjectInformation->FileId.Cell,
+ pFcb->ObjectInformation->FileId.Volume,
+ pFcb->ObjectInformation->FileId.Vnode,
+ pFcb->ObjectInformation->FileId.Unique,
+ ntStatus);
+
+ try_return( ntStatus);
+ }
+
+ //
+ // Perform a new snapshot of the directory
+ //
+
+ ntStatus = AFSSnapshotDirectory( pFcb,
+ pCcb,
+ FALSE);
+
+ if( !NT_SUCCESS( ntStatus))
+ {
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSQueryDirectory Snapshot directory failure for parent %wZ Mask %wZ Status %08lX\n",
+ &pCcb->DirectoryCB->NameInformation.FileName,
+ &pCcb->MaskName,
+ ntStatus);
+
+ try_return( ntStatus);
+ }
+ }
+
+ AFSConvertToShared( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+
+ //
// We can now safely drop the lock on the node
//
{
ntStatus = AFSSnapshotDirectory( pFcb,
- pCcb);
+ pCcb,
+ TRUE);
if( !NT_SUCCESS( ntStatus))
{
FileInformationClass);
try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
- }
+ }
AFSReleaseResource( pFcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
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;
}
}
pCcb->CurrentDirIndex--;
+ InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
try_return( ntStatus = STATUS_SUCCESS);
}
// Now fill the base parts of the structure that are applicable.
case FileIdBothDirectoryInformation:
case FileBothDirectoryInformation:
-
+ {
pBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&pBuffer[ ulNextEntry];
pBothDirInfo->ShortNameLength = (CHAR)pDirEntry->NameInformation.ShortNameLength;
&pDirEntry->NameInformation.ShortName[ 0],
pBothDirInfo->ShortNameLength);
}
+ }
case FileIdFullDirectoryInformation:
case FileFullDirectoryInformation:
-
+ {
pFullDirInfo = (PFILE_FULL_DIR_INFORMATION)&pBuffer[ ulNextEntry];
pFullDirInfo->EaSize = 0;
-
+ }
case FileDirectoryInformation:
-
+ {
pDirInfo = (PFILE_DIRECTORY_INFORMATION)&pBuffer[ ulNextEntry];
if( bUseFileInfo)
pDirInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
break;
+ }
case FileNamesInformation:
-
+ {
pNamesInfo = (PFILE_NAMES_INFORMATION)&pBuffer[ ulNextEntry];
pNamesInfo->FileIndex = pDirEntry->FileIndex;
pNamesInfo->FileNameLength = pDirEntry->NameInformation.FileName.Length;
break;
-
+ }
default:
-
+ {
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
"AFSQueryDirectory (%08lX) Unknown FileInformationClass %u\n",
Irp,
FileInformationClass);
+ InterlockedDecrement( &pDirEntry->OpenReferenceCount);
+
try_return( ntStatus = STATUS_INVALID_INFO_CLASS);
break;
+ }
}
ulBytesConverted = ulBytesRemainingInBuffer - ulBaseLength >= pDirEntry->NameInformation.FileName.Length ?
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
// 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:
NTSTATUS
AFSSnapshotDirectory( IN AFSFcb *Fcb,
- IN AFSCcb *Ccb)
+ IN AFSCcb *Ccb,
+ IN BOOLEAN ResetIndex)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
__Enter
{
- //
- // Set it up so we still get the . and .. entries for empty directories
- //
-
- if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
+ if( ResetIndex)
{
- Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
- }
- else
- {
+ //
+ // Set it up so we still get the . and .. entries for empty directories
+ //
+
+ if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES))
+ {
- Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
+ Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_DIR_INDEX;
+ }
+ else
+ {
+
+ Ccb->CurrentDirIndex = AFS_DIR_ENTRY_INITIAL_ROOT_INDEX;
+ }
}
if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeCount == 0)