ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
+ if( BooleanFlagOn( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
+ {
+
+ try_return( ntStatus = STATUS_SUCCESS);
+ }
+
uniGUID.Length = 0;
uniGUID.MaximumLength = 0;
uniGUID.Buffer = NULL;
AuthGroup,
NULL,
&ObjectInfoCB->FileId,
+ ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
+ ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
(void *)pDirQueryCB,
sizeof( AFSDirQueryCB),
pBuffer,
// The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
//
- lCount = AFSObjectInfoIncrement( pObjectInfo);
+ lCount = AFSObjectInfoIncrement( pObjectInfo,
+ AFS_OBJECT_REFERENCE_INVALIDATION);
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
+ pObjectInfo,
+ lCount);
AFSPerformObjectInvalidate( pObjectInfo,
AFS_INVALIDATE_DATA_VERSION);
// Need to tear down this entry and rebuild it below
//
- if( pDirNode->DirOpenReferenceCount <= 0)
+ if( pDirNode->DirOpenReferenceCount <= 0 &&
+ pDirNode->NameArrayReferenceCount <= 0)
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
}
- //
- // If the processing failed then we should reset the directory content in the event
- // it is re-enumerated
- //
+ if ( NT_SUCCESS( ntStatus))
+ {
- if( !NT_SUCCESS( ntStatus))
+ SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
+ }
+ else
{
+ //
+ // If the processing failed then we should reset the directory
+ // content in the event it is re-enumerated
+ //
+
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
"AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
AuthGroup,
NULL,
FileId,
+ NULL,
+ 0,
(void *)&stDirQueryCB,
sizeof( AFSDirQueryCB),
NULL,
AuthGroup,
NULL,
&ObjectInfoCB->FileId,
+ ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
+ ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
(void *)pDirQueryCB,
sizeof( AFSDirQueryCB),
pBuffer,
// lock hierarchy.
//
- lCount = AFSObjectInfoIncrement( pObjectInfo);
+ lCount = AFSObjectInfoIncrement( pObjectInfo,
+ AFS_OBJECT_REFERENCE_INVALIDATION);
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
+ pObjectInfo,
+ lCount);
if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
AFS_INVALIDATE_DATA_VERSION)))
{
- lCount = AFSObjectInfoDecrement( pObjectInfo);
+ lCount = AFSObjectInfoDecrement( pObjectInfo,
+ AFS_OBJECT_REFERENCE_INVALIDATION);
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
+ pObjectInfo,
+ lCount);
}
}
else
// Need to tear down this entry and rebuild it below
//
- if( pDirNode->DirOpenReferenceCount <= 0)
+ if( pDirNode->DirOpenReferenceCount <= 0 &&
+ pDirNode->NameArrayReferenceCount <= 0)
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AuthGroup,
FileName,
NULL,
+ NULL,
+ 0,
&stCreateCB,
sizeof( AFSFileCreateCB),
pResultCB,
pResultCB->DirEnum.FileId.Vnode,
pResultCB->DirEnum.FileId.Unique);
- if( pDirNode->DirOpenReferenceCount <= 0)
+ if( pDirNode->DirOpenReferenceCount <= 0 &&
+ pDirNode->NameArrayReferenceCount <= 0)
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AuthGroup,
NULL,
&ObjectInfo->FileId,
+ ObjectInfo->VolumeCB->VolumeInformation.Cell,
+ ObjectInfo->VolumeCB->VolumeInformation.CellLength,
&stUpdateCB,
sizeof( AFSFileUpdateCB),
pUpdateResultCB,
AFSFileDeleteCB stDelete;
AFSFileDeleteResultCB stDeleteResult;
ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+ AFSObjectInfoCB *pObjectInfo = NULL;
+ AFSObjectInfoCB *pParentObjectInfo = NULL;
__Enter
{
- stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
+ pObjectInfo = DirectoryCB->ObjectInformation;
+
+ pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
+ &pObjectInfo->ParentFileId);
+
+ stDelete.ParentId = pObjectInfo->ParentFileId;
stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
ulRequestFlags,
AuthGroup,
&DirectoryCB->NameInformation.FileName,
- &DirectoryCB->ObjectInformation->FileId,
+ &pObjectInfo->FileId,
+ pObjectInfo->VolumeCB->VolumeInformation.Cell,
+ pObjectInfo->VolumeCB->VolumeInformation.CellLength,
&stDelete,
sizeof( AFSFileDeleteCB),
&stDeleteResult,
stDelete.ParentId.Vnode,
stDelete.ParentId.Unique,
&DirectoryCB->NameInformation.FileName,
- DirectoryCB->ObjectInformation->FileId.Cell,
- DirectoryCB->ObjectInformation->FileId.Volume,
- DirectoryCB->ObjectInformation->FileId.Vnode,
- DirectoryCB->ObjectInformation->FileId.Unique,
+ pObjectInfo->FileId.Cell,
+ pObjectInfo->FileId.Volume,
+ pObjectInfo->FileId.Vnode,
+ pObjectInfo->FileId.Unique,
ntStatus);
try_return( ntStatus);
}
- AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+ AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
TRUE);
if( CheckOnly)
// Validate the parent data version
//
- if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
+ if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
{
- SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+ SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
- DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+ pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
}
}
else
// Update the parent data version
//
- if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
+ if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
{
- SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+ SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
- DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+ pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
}
else
{
// Directory data version number can be updated. Until then we must force
// a verification.
//
- // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
+ // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
//
- SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+ SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
- DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+ pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
}
}
- AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+ AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
try_exit:
- NOTHING;
+ if ( pParentObjectInfo)
+ {
+
+ AFSReleaseObjectInfo( &pParentObjectInfo);
+ }
}
return ntStatus;
AuthGroup,
&SourceDirectoryCB->NameInformation.FileName,
&ObjectInfo->FileId,
+ ObjectInfo->VolumeCB->VolumeInformation.Cell,
+ ObjectInfo->VolumeCB->VolumeInformation.CellLength,
pHardLinkCB,
sizeof( AFSFileHardLinkCB) + TargetName->Length,
pResultCB,
pResultCB->DirEnum.FileId.Vnode,
pResultCB->DirEnum.FileId.Unique);
- if( pDirNode->DirOpenReferenceCount <= 0)
+ if( pDirNode->DirOpenReferenceCount <= 0 &&
+ pDirNode->NameArrayReferenceCount <= 0)
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AuthGroup,
&DirectoryCB->NameInformation.FileName,
&ObjectInfo->FileId,
+ ObjectInfo->VolumeCB->VolumeInformation.Cell,
+ ObjectInfo->VolumeCB->VolumeInformation.CellLength,
pRenameCB,
sizeof( AFSFileRenameCB) + TargetName->Length,
pRenameResultCB,
AFSFileEvalResultCB *pEvalResultCB = NULL;
AFSDirEnumEntry *pDirEnumCB = NULL;
ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
- AFSObjectInfoCB *pParentInfo = NULL;
+ AFSObjectInfoCB *pParentObjectInfo = NULL;
__Enter
{
RtlZeroMemory( &stTargetID,
sizeof( AFSEvalTargetCB));
- pParentInfo = ObjectInfo->ParentObjectInformation;
-
- if( pParentInfo != NULL)
+ if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
{
- stTargetID.ParentId = pParentInfo->FileId;
+ pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
+ &ObjectInfo->ParentFileId);
+
+ stTargetID.ParentId = ObjectInfo->ParentFileId;
}
//
AuthGroup,
NULL,
&ObjectInfo->FileId,
+ ObjectInfo->VolumeCB->VolumeInformation.Cell,
+ ObjectInfo->VolumeCB->VolumeInformation.CellLength,
&stTargetID,
sizeof( AFSEvalTargetCB),
pEvalResultCB,
if( ntStatus == STATUS_OBJECT_PATH_INVALID)
{
- if( pParentInfo != NULL)
+ if( pParentObjectInfo != NULL)
{
- AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+ AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
TRUE);
- SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+ SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
- pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+ pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
- AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+ AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
}
}
}
//
+ // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
+ // ObjectInfo->FileType is something else. The same is true for
+ // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
+ // to ensure consistency. An inconsistent pDirEnumEntry can be
+ // produced as a result of invalid status info received from a file
+ // server. If the types are inconsistent or if the type does not
+ // match the implied type derived from the vnode (odd values are
+ // directories and even values are other types), prevent the request
+ // from completing successfully. This may prevent access to the file or
+ // directory but will prevent a BSOD.
+ //
+
+ if ( !AFSIsEqualFID( &ObjectInfo->FileId,
+ &pEvalResultCB->DirEnum.FileId))
+ {
+
+ try_return( ntStatus = STATUS_UNSUCCESSFUL);
+ }
+
+ switch ( pEvalResultCB->DirEnum.FileType)
+ {
+
+ case AFS_FILE_TYPE_DIRECTORY:
+ if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
+ {
+
+ try_return( ntStatus = STATUS_UNSUCCESSFUL);
+ }
+
+ if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
+ ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
+ {
+
+ try_return( ntStatus = STATUS_UNSUCCESSFUL);
+ }
+
+ break;
+
+ case AFS_FILE_TYPE_FILE:
+ if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
+ {
+
+ try_return( ntStatus = STATUS_UNSUCCESSFUL);
+ }
+
+ if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
+ ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
+ {
+
+ try_return( ntStatus = STATUS_UNSUCCESSFUL);
+ }
+
+ break;
+ }
+
+ //
// Validate the parent data version
//
- if ( pParentInfo != NULL)
+ if ( pParentObjectInfo != NULL)
{
- AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+ AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
TRUE);
- if ( pParentInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
+ if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
{
- SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+ SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
- pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+ pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
}
- AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+ AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
}
//
try_exit:
+ if ( pParentObjectInfo != NULL)
+ {
+
+ AFSReleaseObjectInfo( &pParentObjectInfo);
+ }
+
if( pEvalResultCB != NULL)
{
AFSEvaluateTargetByName( IN GUID *AuthGroup,
IN AFSObjectInfoCB *ParentObjectInfo,
IN PUNICODE_STRING SourceName,
+ IN ULONG Flags,
OUT AFSDirEnumEntry **DirEnumEntry)
{
ulResultBufferLength = PAGE_SIZE;
ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
- AFS_REQUEST_FLAG_SYNCHRONOUS,
+ AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
AuthGroup,
SourceName,
NULL,
+ ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
+ ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
&stTargetID,
sizeof( AFSEvalTargetCB),
pEvalResultCB,
FileID,
NULL,
0,
+ NULL,
+ 0,
VolumeInformation,
&ulResultLen);
FileID,
NULL,
0,
+ NULL,
+ 0,
VolumeSizeInformation,
&ulResultLen);
&Ccb->AuthGroup,
&Ccb->DirectoryCB->NameInformation.FileName,
NULL,
+ NULL,
+ 0,
pIoRequest,
sizeof( AFSPipeIORequestCB) + InputLength,
pOutputSystemBuffer,
&Ccb->AuthGroup,
&Ccb->DirectoryCB->NameInformation.FileName,
NULL,
+ NULL,
+ 0,
pInfoRequest,
sizeof( AFSPipeInfoRequestCB) + InputLength,
NULL,
&Ccb->AuthGroup,
&Ccb->DirectoryCB->NameInformation.FileName,
NULL,
+ NULL,
+ 0,
&stInfoRequest,
sizeof( AFSPipeInfoRequestCB),
DataBuffer,
NULL,
0,
NULL,
+ 0,
+ NULL,
NULL);
}