@@ -371,21 +371,101 @@ static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Cont
371371 return AlreadyRead ;
372372}
373373
374- static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper (PNTFS_VOLUME_INFO Volume , PNTFS_ATTR_RECORD AttrRecord , PNTFS_ATTR_RECORD AttrRecordEnd , ULONG Type , const WCHAR * Name , ULONG NameLength )
374+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper (
375+ PNTFS_VOLUME_INFO Volume ,
376+ PNTFS_ATTR_RECORD AttrRecord ,
377+ PNTFS_ATTR_RECORD AttrRecordEnd ,
378+ ULONG Type ,
379+ const WCHAR * Name ,
380+ ULONG NameLength ,
381+ ULONG Recursion );
382+ static BOOLEAN NtfsReadMftRecord (PNTFS_VOLUME_INFO Volume , ULONGLONG MFTIndex , PNTFS_MFT_RECORD Buffer );
383+
384+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList (
385+ PNTFS_VOLUME_INFO Volume ,
386+ PNTFS_ATTR_LIST_ATTR AttrListRecord ,
387+ PNTFS_ATTR_LIST_ATTR AttrListRecordEnd ,
388+ ULONG Type ,
389+ const WCHAR * Name ,
390+ ULONG NameLength ,
391+ ULONG Recursion )
392+ {
393+ PNTFS_MFT_RECORD MftRecord = FrLdrTempAlloc (Volume -> MftRecordSize , TAG_NTFS_MFT );
394+ if (!MftRecord )
395+ return NULL ;
396+
397+ while (AttrListRecord < AttrListRecordEnd )
398+ {
399+ ULONGLONG MftIndex = AttrListRecord -> BaseFileRef & 0xFFFFFFFFFFFF ;
400+ ULONG AttrType = AttrListRecord -> Type ;
401+
402+ if (AttrType == NTFS_ATTR_TYPE_END )
403+ break ;
404+
405+ TRACE ("Recursion = %u, AttrListRecord->Type = 0x%x\n" , Recursion , AttrType );
406+
407+ if (AttrType == Type &&
408+ AttrListRecord -> NameLength == NameLength )
409+ {
410+ PWCHAR AttrListName ;
411+
412+ AttrListName = (PWCHAR )((PCHAR )AttrListRecord + AttrListRecord -> NameOffset );
413+ if (RtlEqualMemory (AttrListName , Name , NameLength << 1 ))
414+ {
415+ PNTFS_ATTR_CONTEXT Context ;
416+ PNTFS_ATTR_RECORD AttrRecord ;
417+ PNTFS_ATTR_RECORD AttrRecordEnd ;
418+
419+ if (!NtfsReadMftRecord (Volume , MftIndex , MftRecord ))
420+ goto skip ;
421+
422+ AttrRecord = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + MftRecord -> AttributesOffset );
423+ AttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + Volume -> MftRecordSize );
424+
425+ Context = NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength , Recursion + 1 );
426+ if (Context )
427+ {
428+ FrLdrTempFree (MftRecord , TAG_NTFS_MFT );
429+ return Context ;
430+ }
431+ }
432+ }
433+
434+ skip :
435+ if (AttrListRecord -> RecLength == 0 )
436+ break ;
437+ AttrListRecord = (PNTFS_ATTR_LIST_ATTR )((PCHAR )AttrListRecord + AttrListRecord -> RecLength );
438+ }
439+
440+ FrLdrTempFree (MftRecord , TAG_NTFS_MFT );
441+ return NULL ;
442+ }
443+
444+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper (
445+ PNTFS_VOLUME_INFO Volume ,
446+ PNTFS_ATTR_RECORD AttrRecord ,
447+ PNTFS_ATTR_RECORD AttrRecordEnd ,
448+ ULONG Type ,
449+ const WCHAR * Name ,
450+ ULONG NameLength ,
451+ ULONG Recursion )
375452{
376453 while (AttrRecord < AttrRecordEnd )
377454 {
378455 if (AttrRecord -> Type == NTFS_ATTR_TYPE_END )
379456 break ;
380457
381- if (AttrRecord -> Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST )
458+ TRACE ("Recursion = %u, AttrRecord->Type = 0x%x\n" , Recursion , AttrRecord -> Type );
459+
460+ /* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
461+ if (AttrRecord -> Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < 8 )
382462 {
383463 PNTFS_ATTR_CONTEXT Context ;
384464 PNTFS_ATTR_CONTEXT ListContext ;
385465 PVOID ListBuffer ;
386466 ULONGLONG ListSize ;
387- PNTFS_ATTR_RECORD ListAttrRecord ;
388- PNTFS_ATTR_RECORD ListAttrRecordEnd ;
467+ PNTFS_ATTR_LIST_ATTR ListAttrRecord ;
468+ PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd ;
389469
390470 ListContext = NtfsPrepareAttributeContext (AttrRecord );
391471
@@ -401,13 +481,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401481 continue ;
402482 }
403483
404- ListAttrRecord = (PNTFS_ATTR_RECORD )ListBuffer ;
405- ListAttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )ListBuffer + ListSize );
484+ ListAttrRecord = (PNTFS_ATTR_LIST_ATTR )ListBuffer ;
485+ ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR )((PCHAR )ListBuffer + ListSize );
406486
407487 if (NtfsReadAttribute (Volume , ListContext , 0 , ListBuffer , (ULONG )ListSize ) == ListSize )
408488 {
409- Context = NtfsFindAttributeHelper (Volume , ListAttrRecord , ListAttrRecordEnd ,
410- Type , Name , NameLength );
489+ Context = NtfsFindAttributeHelperList (Volume , ListAttrRecord , ListAttrRecordEnd ,
490+ Type , Name , NameLength , Recursion + 1 );
411491
412492 NtfsReleaseAttributeContext (ListContext );
413493 FrLdrTempFree (ListBuffer , TAG_NTFS_LIST );
@@ -417,23 +497,22 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
417497 }
418498 }
419499
420- if (AttrRecord -> Type == Type )
500+ if (AttrRecord -> Type == Type &&
501+ AttrRecord -> NameLength == NameLength &&
502+ NtfsGetAttributeSize (AttrRecord ) != 0 )
421503 {
422- if (AttrRecord -> NameLength == NameLength )
423- {
424- PWCHAR AttrName ;
504+ PWCHAR AttrName ;
425505
426- AttrName = (PWCHAR )((PCHAR )AttrRecord + AttrRecord -> NameOffset );
427- if (RtlEqualMemory (AttrName , Name , NameLength << 1 ))
428- {
429- /* Found it, fill up the context and return. */
430- return NtfsPrepareAttributeContext (AttrRecord );
431- }
506+ AttrName = (PWCHAR )((PCHAR )AttrRecord + AttrRecord -> NameOffset );
507+ if (RtlEqualMemory (AttrName , Name , NameLength << 1 ))
508+ {
509+ /* Found it, fill up the context and return. */
510+ return NtfsPrepareAttributeContext (AttrRecord );
432511 }
433512 }
434513
435514 if (AttrRecord -> Length == 0 )
436- return NULL ;
515+ break ;
437516 AttrRecord = (PNTFS_ATTR_RECORD )((PCHAR )AttrRecord + AttrRecord -> Length );
438517 }
439518
@@ -451,7 +530,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
451530 for (NameLength = 0 ; Name [NameLength ] != 0 ; NameLength ++ )
452531 ;
453532
454- return NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength );
533+ return NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength , 0 );
455534}
456535
457536static BOOLEAN NtfsFixupRecord (PNTFS_VOLUME_INFO Volume , PNTFS_RECORD Record )
@@ -592,6 +671,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
592671 while (IndexEntry < IndexEntryEnd &&
593672 !(IndexEntry -> Flags & NTFS_INDEX_ENTRY_END ))
594673 {
674+ TRACE ("%s " , FileName );
595675 if (NtfsCompareFileName (FileName , IndexEntry ))
596676 {
597677 * OutMFTIndex = (IndexEntry -> Data .Directory .IndexedFile & NTFS_MFT_MASK );
@@ -675,6 +755,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
675755 while (IndexEntry < IndexEntryEnd &&
676756 !(IndexEntry -> Flags & NTFS_INDEX_ENTRY_END ))
677757 {
758+ TRACE ("%s " , FileName );
678759 if (NtfsCompareFileName (FileName , IndexEntry ))
679760 {
680761 TRACE ("File found\n" );
0 commit comments