@@ -371,21 +371,113 @@ 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 BOOLEAN NtfsFixupRecord (PNTFS_VOLUME_INFO Volume , PNTFS_RECORD Record )
375+ {
376+ USHORT * USA ;
377+ USHORT USANumber ;
378+ USHORT USACount ;
379+ USHORT * Block ;
380+
381+ USA = (USHORT * )((PCHAR )Record + Record -> USAOffset );
382+ USANumber = * (USA ++ );
383+ USACount = Record -> USACount - 1 ; /* Exclude the USA Number. */
384+ Block = (USHORT * )((PCHAR )Record + Volume -> BootSector .BytesPerSector - 2 );
385+
386+ while (USACount )
387+ {
388+ if (* Block != USANumber )
389+ return FALSE;
390+ * Block = * (USA ++ );
391+ Block = (USHORT * )((PCHAR )Block + Volume -> BootSector .BytesPerSector );
392+ USACount -- ;
393+ }
394+
395+ return TRUE;
396+ }
397+
398+ static BOOLEAN NtfsReadMftRecord (PNTFS_VOLUME_INFO Volume , ULONGLONG MFTIndex , PNTFS_MFT_RECORD Buffer )
399+ {
400+ ULONGLONG BytesRead ;
401+
402+ BytesRead = NtfsReadAttribute (Volume , Volume -> MFTContext , MFTIndex * Volume -> MftRecordSize , (PCHAR )Buffer , Volume -> MftRecordSize );
403+ if (BytesRead != Volume -> MftRecordSize )
404+ return FALSE;
405+
406+ /* Apply update sequence array fixups. */
407+ return NtfsFixupRecord (Volume , (PNTFS_RECORD )Buffer );
408+ }
409+
410+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper (PNTFS_VOLUME_INFO Volume , PNTFS_ATTR_RECORD AttrRecord , PNTFS_ATTR_RECORD AttrRecordEnd , ULONG Type , const WCHAR * Name , ULONG NameLength , ULONG Recursion );
411+
412+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList (PNTFS_VOLUME_INFO Volume , PNTFS_ATTR_LIST_ATTR AttrListRecord , PNTFS_ATTR_LIST_ATTR AttrListRecordEnd , ULONG Type , const WCHAR * Name , ULONG NameLength , ULONG Recursion )
413+ {
414+ PNTFS_MFT_RECORD MftRecord = FrLdrTempAlloc (Volume -> MftRecordSize , TAG_NTFS_MFT );
415+ if (!MftRecord )
416+ return NULL ;
417+
418+ while (AttrListRecord < AttrListRecordEnd )
419+ {
420+ ULONGLONG MftIndex = AttrListRecord -> BaseFileRef & 0xFFFFFFFFFFFF ;
421+ ULONG AttrType = AttrListRecord -> Type ;
422+
423+ if (AttrType == NTFS_ATTR_TYPE_END )
424+ break ;
425+
426+ TRACE ("Recursion = %u, AttrListRecord->Type = 0x%x\n" , Recursion , AttrListRecord -> Type );
427+
428+ if (AttrListRecord -> Type == Type && AttrListRecord -> NameLength == NameLength )
429+ {
430+ PWCHAR AttrListName ;
431+
432+ AttrListName = (PWCHAR )((PCHAR )AttrListRecord + AttrListRecord -> NameOffset );
433+ if (RtlEqualMemory (AttrListName , Name , NameLength << 1 ))
434+ {
435+ PNTFS_ATTR_CONTEXT Context ;
436+ PNTFS_ATTR_RECORD AttrRecord ;
437+ PNTFS_ATTR_RECORD AttrRecordEnd ;
438+
439+ if (!NtfsReadMftRecord (Volume , MftIndex , MftRecord ))
440+ goto skip ;
441+
442+ AttrRecord = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + MftRecord -> AttributesOffset );
443+ AttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + MftRecord -> BytesInUse );
444+
445+ Context = NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength , Recursion + 1 );
446+ if (Context )
447+ {
448+ FrLdrTempFree (MftRecord , TAG_NTFS_MFT );
449+ return Context ;
450+ }
451+ }
452+ }
453+
454+ skip :
455+ if (AttrListRecord -> RecLength == 0 )
456+ break ;
457+ AttrListRecord = (PNTFS_ATTR_LIST_ATTR )((PCHAR )AttrListRecord + AttrListRecord -> RecLength );
458+ }
459+
460+ FrLdrTempFree (MftRecord , TAG_NTFS_MFT );
461+ return NULL ;
462+ }
463+
464+ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper (PNTFS_VOLUME_INFO Volume , PNTFS_ATTR_RECORD AttrRecord , PNTFS_ATTR_RECORD AttrRecordEnd , ULONG Type , const WCHAR * Name , ULONG NameLength , ULONG Recursion )
375465{
376466 while (AttrRecord < AttrRecordEnd )
377467 {
378468 if (AttrRecord -> Type == NTFS_ATTR_TYPE_END )
379469 break ;
380470
381- if (AttrRecord -> Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST )
471+ TRACE ("Recursion = %u, AttrRecord->Type = 0x%x\n" , Recursion , AttrRecord -> Type );
472+
473+ if (AttrRecord -> Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < 8 )
382474 {
383475 PNTFS_ATTR_CONTEXT Context ;
384476 PNTFS_ATTR_CONTEXT ListContext ;
385477 PVOID ListBuffer ;
386478 ULONGLONG ListSize ;
387- PNTFS_ATTR_RECORD ListAttrRecord ;
388- PNTFS_ATTR_RECORD ListAttrRecordEnd ;
479+ PNTFS_ATTR_LIST_ATTR ListAttrRecord ;
480+ PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd ;
389481
390482 ListContext = NtfsPrepareAttributeContext (AttrRecord );
391483
@@ -401,13 +493,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401493 continue ;
402494 }
403495
404- ListAttrRecord = (PNTFS_ATTR_RECORD )ListBuffer ;
405- ListAttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )ListBuffer + ListSize );
496+ ListAttrRecord = (PNTFS_ATTR_LIST_ATTR )ListBuffer ;
497+ ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR )((PCHAR )ListBuffer + ListSize );
406498
407499 if (NtfsReadAttribute (Volume , ListContext , 0 , ListBuffer , (ULONG )ListSize ) == ListSize )
408500 {
409- Context = NtfsFindAttributeHelper (Volume , ListAttrRecord , ListAttrRecordEnd ,
410- Type , Name , NameLength );
501+ Context = NtfsFindAttributeHelperList (Volume , ListAttrRecord , ListAttrRecordEnd ,
502+ Type , Name , NameLength , Recursion + 1 );
411503
412504 NtfsReleaseAttributeContext (ListContext );
413505 FrLdrTempFree (ListBuffer , TAG_NTFS_LIST );
@@ -419,7 +511,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
419511
420512 if (AttrRecord -> Type == Type )
421513 {
422- if (AttrRecord -> NameLength == NameLength )
514+ if (AttrRecord -> NameLength == NameLength && NtfsGetAttributeSize ( AttrRecord ) != 0 )
423515 {
424516 PWCHAR AttrName ;
425517
@@ -433,7 +525,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
433525 }
434526
435527 if (AttrRecord -> Length == 0 )
436- return NULL ;
528+ break ;
437529 AttrRecord = (PNTFS_ATTR_RECORD )((PCHAR )AttrRecord + AttrRecord -> Length );
438530 }
439531
@@ -447,47 +539,11 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
447539 ULONG NameLength ;
448540
449541 AttrRecord = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + MftRecord -> AttributesOffset );
450- AttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + Volume -> MftRecordSize );
542+ AttrRecordEnd = (PNTFS_ATTR_RECORD )((PCHAR )MftRecord + MftRecord -> BytesInUse );
451543 for (NameLength = 0 ; Name [NameLength ] != 0 ; NameLength ++ )
452544 ;
453545
454- return NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength );
455- }
456-
457- static BOOLEAN NtfsFixupRecord (PNTFS_VOLUME_INFO Volume , PNTFS_RECORD Record )
458- {
459- USHORT * USA ;
460- USHORT USANumber ;
461- USHORT USACount ;
462- USHORT * Block ;
463-
464- USA = (USHORT * )((PCHAR )Record + Record -> USAOffset );
465- USANumber = * (USA ++ );
466- USACount = Record -> USACount - 1 ; /* Exclude the USA Number. */
467- Block = (USHORT * )((PCHAR )Record + Volume -> BootSector .BytesPerSector - 2 );
468-
469- while (USACount )
470- {
471- if (* Block != USANumber )
472- return FALSE;
473- * Block = * (USA ++ );
474- Block = (USHORT * )((PCHAR )Block + Volume -> BootSector .BytesPerSector );
475- USACount -- ;
476- }
477-
478- return TRUE;
479- }
480-
481- static BOOLEAN NtfsReadMftRecord (PNTFS_VOLUME_INFO Volume , ULONGLONG MFTIndex , PNTFS_MFT_RECORD Buffer )
482- {
483- ULONGLONG BytesRead ;
484-
485- BytesRead = NtfsReadAttribute (Volume , Volume -> MFTContext , MFTIndex * Volume -> MftRecordSize , (PCHAR )Buffer , Volume -> MftRecordSize );
486- if (BytesRead != Volume -> MftRecordSize )
487- return FALSE;
488-
489- /* Apply update sequence array fixups. */
490- return NtfsFixupRecord (Volume , (PNTFS_RECORD )Buffer );
546+ return NtfsFindAttributeHelper (Volume , AttrRecord , AttrRecordEnd , Type , Name , NameLength , 0 );
491547}
492548
493549#if DBG
@@ -592,6 +648,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
592648 while (IndexEntry < IndexEntryEnd &&
593649 !(IndexEntry -> Flags & NTFS_INDEX_ENTRY_END ))
594650 {
651+ TRACE ("%s " , FileName );
595652 if (NtfsCompareFileName (FileName , IndexEntry ))
596653 {
597654 * OutMFTIndex = (IndexEntry -> Data .Directory .IndexedFile & NTFS_MFT_MASK );
@@ -675,6 +732,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
675732 while (IndexEntry < IndexEntryEnd &&
676733 !(IndexEntry -> Flags & NTFS_INDEX_ENTRY_END ))
677734 {
735+ TRACE ("%s " , FileName );
678736 if (NtfsCompareFileName (FileName , IndexEntry ))
679737 {
680738 TRACE ("File found\n" );
0 commit comments