Reversed disassembly of the XP NTFS bootstrap code

by rwid

Code routine comments are here, but no detailed code or structure comments. The symbolic names used here may or may not be helpful. Feel free to ask for more details ;)

seg000:0000 seg000          segment byte public 'CODE' use16
seg000:0000                 assume cs:seg000
seg000:0000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:0000
seg000:0000 start:
seg000:0000                 jmp     short near ptr BootSectorMain
seg000:0002 ; ---------------------------------------------------------------------------
seg000:0002                 nop
seg000:0002 ; ---------------------------------------------------------------------------
seg000:0003 NtfsBpbEbpb     db 'N', 'T', 'F', 'S'   ; OemId
seg000:0003                 db ' ', ' ', ' ', ' '   ; OemId
seg000:0003                 dw 200h                 ; BytesPerSector
seg000:0003                 db 8                    ; SectorsPerCluster
seg000:0003                 dw 0                    ; NoOfSectorsToRead
seg000:0003                 dd 0                    ; LsnToRead
seg000:0003                 db 0                    ; ExtDiskAccessAvl
seg000:0003                 db 0F8h                 ; MediaDescriptor
seg000:0003                 db 2 dup(0)
seg000:0003                 dw 3Fh                  ; SectorsPerTrack
seg000:0003                 dw 0FFh                 ; NumberOfHeads
seg000:0003                 dd 3Fh                  ; PartitionBase
seg000:0003                 dd 0                    ; ChsLimit
seg000:0003                 db 80h                  ; DiskNumber
seg000:0003                 db 0, 80h, 0
seg000:0003                 dq 1DFF7E6h             ; TotalSectors
seg000:0003                 dq 0C0000h              ; LcnOfMftBfrs
seg000:0003                 dq 1DFF7Eh              ; LcnOfMftMirrorBfrs
seg000:0003                 dd 0F6h                 ; ClustersPerFrs
seg000:0003                 dd 1                    ; ClustersPerIndexBlock
seg000:0003                 db 0D7h, 4, 72h, 54h    ; VolumeSerialNumber
seg000:0003                 db 2Eh, 72h, 54h, 62h   ; VolumeSerialNumber
seg000:0003                 dd 0                    ; Checksum
seg000:0054
seg000:0054 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0054
seg000:0054 ; Description:
seg000:0054 ;
seg000:0054 ;   Main boot sector routine. The boot sector was loaded
seg000:0054 ;   by the MBR at segmented address 0000:7C00. Reads the
seg000:0054 ;   entire NTFS bootstrap (16 sectors) from the disk and
seg000:0054 ;   passes control to the bootstrap's main routine.
seg000:0054 ;
seg000:0054 ; Arguments:
seg000:0054 ;
seg000:0054 ;   (None)
seg000:0054 ;
seg000:0054 ; Returns:
seg000:0054 ;
seg000:0054 ;   (Does not return. Control is passed to the main
seg000:0054 ;   bootstrap routine.)
seg000:0054
seg000:0054 BootSectorMain  proc far
seg000:0054                 cli
seg000:0055                 xor     ax, ax
seg000:0057                 mov     ss, ax
seg000:0059                 mov     sp, 7C00h
seg000:005C                 sti
seg000:005D                 mov     ax, 7C0h
seg000:0060                 mov     ds, ax
seg000:0062                 assume ds:nothing
seg000:0062                 call    ComputeChsLimit
seg000:0065                 mov     ax, 0D00h
seg000:0068                 mov     es, ax
seg000:006A                 assume es:nothing
seg000:006A                 xor     bx, bx
seg000:006C                 mov     byte ptr ds:NtfsBpbEbpb.NoOfSectorsToRead, 16
seg000:0071                 call    ReadDiskSectors
seg000:0074                 push    0D00h
seg000:0077                 push    offset BootStrapMain
seg000:007A                 retf
seg000:007A BootSectorMain  endp
seg000:007A
seg000:007B
seg000:007B ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:007B
seg000:007B ; Description:
seg000:007B ;
seg000:007B ;   Computes the disk's total sector count according to
seg000:007B ;   the C/H/S values returned by the legacy INT 13 -
seg000:007B ;   DISK - GET DRIVE PARAMETERS bios function. Saves
seg000:007B ;   computed value in the ChsLimit variable. Sectors
seg000:007B ;   at or above this value will require the extended
seg000:007B ;   disk access functions.
seg000:007B ;
seg000:007B ; Arguments:
seg000:007B ;
seg000:007B ;   (None)
seg000:007B ;
seg000:007B ; Returns:
seg000:007B ;
seg000:007B ;   (No return value)
seg000:007B ;
seg000:007B ; Preserves/modifies:
seg000:007B ;
seg000:007B ;   (No explicit preservations)
seg000:007B
seg000:007B ComputeChsLimit proc near
seg000:007B                 mov     dl, ds:NtfsBpbEbpb.DiskNumber
seg000:007F                 mov     ah, 8
seg000:0081                 int     13h
seg000:0083                 jnb     short succeeded
seg000:0085                 mov     cx, 0FFFFh
seg000:0088                 mov     dh, cl
seg000:008A
seg000:008A succeeded:
seg000:008A                 movzx   eax, dh
seg000:008E                 inc     ax
seg000:008F                 movzx   edx, cl
seg000:0093                 and     dl, 3Fh
seg000:0096                 mul     dx
seg000:0098                 xchg    cl, ch
seg000:009A                 shr     ch, 6
seg000:009D                 inc     cx
seg000:009E                 movzx   ecx, cx
seg000:00A2                 mul     ecx
seg000:00A5                 mov     ds:NtfsBpbEbpb.ChsLimit, eax
seg000:00A9                 retn
seg000:00A9 ComputeChsLimit endp
seg000:00A9
seg000:00AA
seg000:00AA ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:00AA
seg000:00AA ; Description:
seg000:00AA ;
seg000:00AA ;   Performs a check for the extended disk access bios
seg000:00AA ;   functions. Sets the ExtDiskAccessAvl boolean
seg000:00AA ;   variable to 1 if they are available.
seg000:00AA ;
seg000:00AA ; Arguments:
seg000:00AA ;
seg000:00AA ;   (None)
seg000:00AA ;
seg000:00AA ; Returns:
seg000:00AA ;
seg000:00AA ;   (No return value)
seg000:00AA ;
seg000:00AA ; Preserves/modifies:
seg000:00AA ;
seg000:00AA ;   (No explicit preservations)
seg000:00AA
seg000:00AA CheckExtDiskAccessAvl proc near
seg000:00AA                 mov     ah, 41h
seg000:00AC                 mov     bx, 55AAh
seg000:00AF                 mov     dl, ds:NtfsBpbEbpb.DiskNumber
seg000:00B3                 int     13h
seg000:00B5                 jb      short failed
seg000:00B7                 cmp     bx, 0AA55h
seg000:00BB                 jnz     short failed
seg000:00BD                 test    cl, 1
seg000:00C0                 jz      short failed
seg000:00C2                 inc     ds:NtfsBpbEbpb.ExtDiskAccessAvl
seg000:00C6
seg000:00C6 failed:
seg000:00C6                 retn
seg000:00C6 CheckExtDiskAccessAvl endp
seg000:00C6
seg000:00C7
seg000:00C7 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:00C7
seg000:00C7 ; Description:
seg000:00C7 ;
seg000:00C7 ;   Reads the specified number of sectors from the
seg000:00C7 ;   specified logical sector number.
seg000:00C7 ;
seg000:00C7 ; Arguments:
seg000:00C7 ;
seg000:00C7 ;   LsnToRead - Logical sector number to read from.
seg000:00C7 ;
seg000:00C7 ;   NoOfSectorsToRead - Number of sectors to read.
seg000:00C7 ;
seg000:00C7 ;   ES:BX - Memory buffer for the sectors to be read.
seg000:00C7 ;
seg000:00C7 ; Returns:
seg000:00C7 ;
seg000:00C7 ;   (No return value. Errors produce a fatal error
seg000:00C7 ;   display message.)
seg000:00C7 ;
seg000:00C7 ; Preserves/modifies:
seg000:00C7 ;
seg000:00C7 ;   Preserves 32-bit GP registers, DS, ES.
seg000:00C7
seg000:00C7 ReadDiskSectors proc near
seg000:00C7                 pushad
seg000:00C9                 push    ds
seg000:00CA                 push    es
seg000:00CB
seg000:00CB read_next_sector:
seg000:00CB                 mov     eax, ds:NtfsBpbEbpb.LsnToRead
seg000:00CF                 add     eax, ds:NtfsBpbEbpb.PartitionBase
seg000:00D4                 cmp     eax, ds:NtfsBpbEbpb.ChsLimit
seg000:00D9                 jb      do_chs_disk_read
seg000:00DD                 push    ds
seg000:00DE                 push    large 0
seg000:00E1                 push    eax
seg000:00E3                 push    es
seg000:00E4                 push    bx
seg000:00E5                 push    large 10010h
seg000:00EB                 cmp     ds:NtfsBpbEbpb.ExtDiskAccessAvl, 0
seg000:00F0                 jnz     do_extended_disk_read
seg000:00F4                 call    CheckExtDiskAccessAvl
seg000:00F7                 cmp     ds:NtfsBpbEbpb.ExtDiskAccessAvl, 0
seg000:00FC                 jz      disk_read_error
seg000:0100
seg000:0100 do_extended_disk_read:
seg000:0100                 mov     ah, 42h
seg000:0102                 mov     dl, ds:NtfsBpbEbpb.DiskNumber
seg000:0106                 push    ss
seg000:0107                 pop     ds
seg000:0108                 assume ds:nothing
seg000:0108                 mov     si, sp
seg000:010A                 int     13h
seg000:010C                 pop     eax
seg000:010E                 pop     bx
seg000:010F                 pop     es
seg000:0110                 assume es:nothing
seg000:0110                 pop     eax
seg000:0112                 pop     eax
seg000:0114                 pop     ds
seg000:0115                 jmp     short check_for_error
seg000:0117 ; ---------------------------------------------------------------------------
seg000:0117
seg000:0117 do_chs_disk_read:
seg000:0117                 xor     edx, edx
seg000:011A                 movzx   ecx, ds:NtfsBpbEbpb.SectorsPerTrack
seg000:0120                 div     ecx
seg000:0123                 inc     dl
seg000:0125                 mov     cl, dl
seg000:0127                 mov     edx, eax
seg000:012A                 shr     edx, 10h
seg000:012E                 div     ds:NtfsBpbEbpb.NumberOfHeads
seg000:0132                 xchg    dl, dh
seg000:0134                 mov     dl, ds:NtfsBpbEbpb.DiskNumber
seg000:0138                 mov     ch, al
seg000:013A                 shl     ah, 6
seg000:013D                 or      cl, ah
seg000:013F                 mov     ax, 201h
seg000:0142                 int     13h
seg000:0144
seg000:0144 check_for_error:
seg000:0144                 jb      disk_read_error
seg000:0148                 mov     ax, es
seg000:014A                 add     ax, 20h
seg000:014D                 mov     es, ax
seg000:014F                 assume es:nothing
seg000:014F                 inc     ds:NtfsBpbEbpb.LsnToRead
seg000:0154                 dec     ds:NtfsBpbEbpb.NoOfSectorsToRead
seg000:0158                 jnz     read_next_sector
seg000:015C                 pop     es
seg000:015D                 assume es:nothing
seg000:015D                 pop     ds
seg000:015E                 popad
seg000:0160                 retn
seg000:0160 ReadDiskSectors endp
seg000:0160
seg000:0161 ; ---------------------------------------------------------------------------
seg000:0161
seg000:0161 disk_read_error:
seg000:0161                 mov     al, ds:diskReadErrorMsg
seg000:0164
seg000:0164 display_error_message:
seg000:0164                 call    DisplayMsg
seg000:0167                 mov     al, ds:restartMsg
seg000:016A                 call    DisplayMsg
seg000:016D                 sti
seg000:016E
seg000:016E error_loop:
seg000:016E                 jmp     short error_loop
seg000:0170
seg000:0170 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0170
seg000:0170 ; Description:
seg000:0170 ;
seg000:0170 ;   Displays the given zero-terminated message string.
seg000:0170 ;
seg000:0170 ; Arguments:
seg000:0170 ;
seg000:0170 ;   AL - Offset (relative to DS:0100) of the
seg000:0170 ;        zero-terminated string to be displayed.
seg000:0170 ;
seg000:0170 ; Returns:
seg000:0170 ;
seg000:0170 ;   (No return value)
seg000:0170 ;
seg000:0170 ; Preserves/modifies:
seg000:0170 ;
seg000:0170 ;   (No explicit preservations)
seg000:0170
seg000:0170 DisplayMsg      proc near
seg000:0170                 mov     ah, 1
seg000:0172                 mov     si, ax
seg000:0174
seg000:0174 loop:
seg000:0174                 lodsb
seg000:0175                 cmp     al, 0
seg000:0177                 jz      short return
seg000:0179                 mov     ah, 0Eh
seg000:017B                 mov     bx, 7
seg000:017E                 int     10h
seg000:0180                 jmp     short loop
seg000:0182 ; ---------------------------------------------------------------------------
seg000:0182
seg000:0182 return:
seg000:0182                 retn
seg000:0182 DisplayMsg      endp
seg000:0182
seg000:0182 ; ---------------------------------------------------------------------------
seg000:0183 aADiskReadErrorOccurred db 0Dh,0Ah
seg000:0183                 db 'A disk read error occurred',0
seg000:01A0 aNtldrIsMissing db 0Dh,0Ah
seg000:01A0                 db 'NTLDR is missing',0
seg000:01B3 aNtldrIsCompressed db 0Dh,0Ah
seg000:01B3                 db 'NTLDR is compressed',0
seg000:01C9 aPressCtrlAltDelToRestart db 0Dh,0Ah
seg000:01C9                 db 'Press Ctrl+Alt+Del to restart',0Dh,0Ah,0
seg000:01EB                 db    0
seg000:01EC                 db    0
seg000:01ED                 db    0
seg000:01EE                 db    0
seg000:01EF                 db    0
seg000:01F0                 db    0
seg000:01F1                 db    0
seg000:01F2                 db    0
seg000:01F3                 db    0
seg000:01F4                 db    0
seg000:01F5                 db    0
seg000:01F6                 db    0
seg000:01F7                 db    0
seg000:01F8 diskReadErrorMsg db 83h
seg000:01F9 ntldrIsMissingMsg db 0A0h
seg000:01FA ntldrIsCompressedMsg db 0B3h
seg000:01FB restartMsg      db 0C9h
seg000:01FC                 db    0
seg000:01FD                 db    0
seg000:01FE                 dw 0AA55h
seg000:0200 aNtldr_length   dw 5
seg000:0202 aNtldr:
seg000:0202                 unicode 0, 
seg000:020C aI30_length     dw 4
seg000:020E aI30:
seg000:020E                 unicode 0, <$I30>
seg000:0216 pAttribListData dd 0E000h
seg000:021A pMftBfrs        dd 3000h
seg000:021E MftFrsCount     dd 0
seg000:0222 pRootdIndexRoot dd 0
seg000:0226 pRootdIndexAlloc dd 0
seg000:022A pRootdBitmap    dd 0
seg000:022E pRootdIndexRootHdr dd 0
seg000:0232 pIndexAllocHdr  dd 0
seg000:0236 pBitmapHdr      dd 0
seg000:023A pNtldrRecord    dd 0
seg000:023E                 dd 0
seg000:0242 pIndexAllocEntry dd 0
seg000:0246 pBitmapData     dd 0
seg000:024A pMftFrInfoEnd   dd 0
seg000:024E BytesPerCluster dd 0
seg000:0252 BytesPerFrs     dd 0
seg000:0256 SectorsPerFrs   dd 909012EBh
seg000:025A pMftFrInfo      dd 0
seg000:025E SizeOfIaEntry   dd 0
seg000:0262 ClustersPerIndxRecd dd 0
seg000:0266 SectorsPerIaEntry dd 0
seg000:026A
seg000:026A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:026A
seg000:026A ; Description:
seg000:026A ;
seg000:026A ;   Main bootstrap routine. Control is passed from the
seg000:026A ;   boot sector's main routine. Locates and loads NTLDR
seg000:026A ;   from the root directory of the boot partition, and
seg000:026A ;   then passes control to NTLDR.
seg000:026A ;
seg000:026A ; Arguments:
seg000:026A ;
seg000:026A ;   (None)
seg000:026A ;
seg000:026A ; Returns:
seg000:026A ;
seg000:026A ;   (Does not return. Control is passed to NTLDR. Errors
seg000:026A ;   produce a fatal error display message.)
seg000:026A
seg000:026A BootStrapMain   proc far
seg000:026A                 mov     ax, cs
seg000:026C                 mov     ds, ax
seg000:026E                 shl     ax, 4
seg000:0271                 cli
seg000:0272                 mov     sp, ax
seg000:0274                 sti
seg000:0275                 call    ComputeChsLimit
seg000:0278                 movzx   eax, ds:NtfsBpbEbpb.BytesPerSector
seg000:027E                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0284                 mul     ebx
seg000:0287                 mov     ds:BytesPerCluster, eax
seg000:028B                 mov     ecx, ds:NtfsBpbEbpb.ClustersPerFrs
seg000:0290                 cmp     cl, 0
seg000:0293                 jg      @@1
seg000:0297                 neg     cl
seg000:0299                 mov     eax, 1
seg000:029F                 shl     eax, cl
seg000:02A2                 jmp     short @@2
seg000:02A4 ; ---------------------------------------------------------------------------
seg000:02A4                 nop
seg000:02A5
seg000:02A5 @@1:
seg000:02A5                 mov     eax, ds:BytesPerCluster
seg000:02A9                 mul     ecx
seg000:02AC
seg000:02AC @@2:
seg000:02AC                 mov     ds:BytesPerFrs, eax
seg000:02B0                 movzx   ebx, ds:NtfsBpbEbpb.BytesPerSector
seg000:02B6                 xor     edx, edx
seg000:02B9                 div     ebx
seg000:02BC                 mov     ds:SectorsPerFrs, eax
seg000:02C0                 call    MftFrInitialize
seg000:02C3                 mov     ecx, ds:pMftFrInfoEnd
seg000:02C8                 mov     ds:pRootdIndexRoot, ecx
seg000:02CD                 add     ecx, ds:BytesPerFrs
seg000:02D2                 mov     ds:pRootdIndexAlloc, ecx
seg000:02D7                 add     ecx, ds:BytesPerFrs
seg000:02DC                 mov     ds:pRootdBitmap, ecx
seg000:02E1                 add     ecx, ds:BytesPerFrs
seg000:02E6                 mov     ds:pNtldrRecord, ecx
seg000:02EB                 add     ecx, ds:BytesPerFrs
seg000:02F0                 mov     ds:pIndexAllocEntry, ecx
seg000:02F5                 mov     eax, $INDEX_ROOT
seg000:02FB                 mov     ecx, ds:pRootdIndexRoot
seg000:0300                 call    GetRootdAttribHdr
seg000:0303                 or      eax, eax
seg000:0306                 jz      disk_read_error
seg000:030A                 mov     ds:pRootdIndexRootHdr, eax
seg000:030E                 mov     eax, $INDEX_ALLOCATION
seg000:0314                 mov     ecx, ds:pRootdIndexAlloc
seg000:0319                 call    GetRootdAttribHdr
seg000:031C                 mov     ds:pIndexAllocHdr, eax
seg000:0320                 mov     eax, $BITMAP
seg000:0326                 mov     ecx, ds:pRootdBitmap
seg000:032B                 call    GetRootdAttribHdr
seg000:032E                 mov     ds:pBitmapHdr, eax
seg000:0332                 mov     eax, ds:pRootdIndexRootHdr
seg000:0336                 or      eax, eax
seg000:0339                 jz      disk_read_error
seg000:033D                 cmp     [eax+STD_ATTRIB_HDR.NonresidentFlag], 0
seg000:0342                 jnz     disk_read_error
seg000:0346                 lea     edx, [eax+(size STD_ATTRIB_HDR)]
seg000:034B                 add     ax, [edx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:034F                 movzx   ecx, [eax+INDEX_ROOT_ATTRIB.ClustersPerIndxRecd]
seg000:0355                 mov     ds:ClustersPerIndxRecd, ecx
seg000:035A                 mov     ecx, [eax+INDEX_ROOT_ATTRIB.SizeOfIaEntry]
seg000:035F                 mov     ds:SizeOfIaEntry, ecx
seg000:0364                 mov     eax, ds:SizeOfIaEntry
seg000:0368                 movzx   ecx, ds:NtfsBpbEbpb.BytesPerSector
seg000:036E                 xor     edx, edx
seg000:0371                 div     ecx
seg000:0374                 mov     ds:SectorsPerIaEntry, eax
seg000:0378                 mov     eax, ds:pIndexAllocEntry
seg000:037C                 add     eax, ds:SizeOfIaEntry
seg000:0381                 mov     ds:pBitmapData, eax
seg000:0385                 cmp     ds:pIndexAllocHdr, 0
seg000:038B                 jz      no_index_allocation
seg000:038F                 cmp     ds:pBitmapHdr, 0
seg000:0395                 jz      disk_read_error
seg000:0399                 mov     ebx, ds:pBitmapHdr
seg000:039E                 push    ds
seg000:039F                 pop     es
seg000:03A0                 mov     edi, ds:pBitmapData
seg000:03A5                 call    GetAttributeData
seg000:03A8
seg000:03A8 no_index_allocation:
seg000:03A8                 movzx   ecx, ds:aNtldr_length
seg000:03AE                 mov     eax, offset aNtldr ; "NTLDR"
seg000:03B4                 call    FindFileInRootdIndex
seg000:03B7                 or      eax, eax
seg000:03BA                 jz      error_ntldr_missing
seg000:03BE                 mov     eax, dword ptr [eax+INDEX_ENTRY.FileReference]
seg000:03C2                 push    ds
seg000:03C3                 pop     es
seg000:03C4                 mov     edi, ds:pNtldrRecord
seg000:03C9                 call    GetFileRecord
seg000:03CC                 mov     eax, ds:pNtldrRecord
seg000:03D0                 mov     ebx, $DATA
seg000:03D6                 mov     ecx, 0
seg000:03DC                 mov     edx, 0
seg000:03E2                 call    FindAttribute
seg000:03E5                 or      eax, eax
seg000:03E8                 jnz     found_attribute
seg000:03EC                 mov     ecx, $DATA
seg000:03F2                 mov     eax, ds:pNtldrRecord
seg000:03F6                 call    GetFrsWithAttribType
seg000:03F9                 or      eax, eax
seg000:03FC                 jz      error_ntldr_missing
seg000:0400                 push    ds
seg000:0401                 pop     es
seg000:0402                 mov     edi, ds:pNtldrRecord
seg000:0407                 call    GetFileRecord
seg000:040A                 mov     eax, ds:pNtldrRecord
seg000:040E                 mov     ebx, $DATA
seg000:0414                 mov     ecx, 0
seg000:041A                 mov     edx, 0
seg000:0420                 call    FindAttribute
seg000:0423                 or      eax, eax
seg000:0426                 jz      error_ntldr_missing
seg000:042A
seg000:042A found_attribute:
seg000:042A                 movzx   ebx, [eax+STD_ATTRIB_HDR.Flags]
seg000:0430                 and     ebx, 0FFh
seg000:0437                 jnz     error_ntldr_compressed
seg000:043B                 mov     ebx, eax
seg000:043E                 push    2000h
seg000:0441                 pop     es
seg000:0442                 assume es:nothing
seg000:0442                 sub     edi, edi
seg000:0445                 call    GetAttributeData
seg000:0448                 mov     dl, ds:NtfsBpbEbpb.DiskNumber
seg000:044C                 mov     ax, 3E8h
seg000:044F                 mov     es, ax
seg000:0451                 assume es:nothing
seg000:0451                 lea     si, NtfsBpbEbpb.BytesPerSector
seg000:0455                 sub     ax, ax
seg000:0457                 push    2000h
seg000:045A                 push    ax
seg000:045B                 retf
seg000:045B BootStrapMain   endp
seg000:045B
seg000:045C
seg000:045C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:045C
seg000:045C ; Description:
seg000:045C ;
seg000:045C ;   Reads the specified number of clusters from the
seg000:045C ;   specified logical cluster number.
seg000:045C ;
seg000:045C ; Arguments:
seg000:045C ;
seg000:045C ;   EAX - Logical cluster number to read from.
seg000:045C ;
seg000:045C ;   EDX - Number of clusters to read.
seg000:045C ;
seg000:045C ;   ES:DI - Memory buffer for the clusters to be read.
seg000:045C ;
seg000:045C ; Returns:
seg000:045C ;
seg000:045C ;   (No return value)
seg000:045C ;
seg000:045C ; Preserves/modifies:
seg000:045C ;
seg000:045C ;   Preserves 32-bit GP registers, DS, ES.
seg000:045C
seg000:045C ReadDiskClusters proc near
seg000:045C                 push    es
seg000:045D                 push    ds
seg000:045E                 pushad
seg000:0460                 mov     ebx, edx
seg000:0463                 movzx   ecx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0469                 mul     ecx
seg000:046C                 mov     ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0470                 mov     eax, ebx
seg000:0473                 mul     ecx
seg000:0476                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:0479                 mov     bx, di
seg000:047B                 and     bx, 0Fh
seg000:047E                 mov     ax, es
seg000:0480                 shr     edi, 4
seg000:0484                 add     ax, di
seg000:0486                 push    ax
seg000:0487                 pop     es
seg000:0488                 assume es:nothing
seg000:0488                 call    ReadDiskSectors
seg000:048B                 popad
seg000:048D                 nop
seg000:048E                 pop     ds
seg000:048F                 pop     es
seg000:0490                 retn
seg000:0490 ReadDiskClusters endp
seg000:0490
seg000:0491
seg000:0491 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0491
seg000:0491 ; Description:
seg000:0491 ;
seg000:0491 ;   Finds the specified attribute in the given file
seg000:0491 ;   record segment.
seg000:0491 ;
seg000:0491 ; Arguments:
seg000:0491 ;
seg000:0491 ;   DS:EAX - Pointer to the file record segment.
seg000:0491 ;
seg000:0491 ;   EBX - Attribute type.
seg000:0491 ;
seg000:0491 ;   ECX - Attribute name length. (Zero for unnamed)
seg000:0491 ;
seg000:0491 ;   DS:EDX - Pointer to the attribute name.
seg000:0491 ;            (Not required for unnamed)
seg000:0491 ;
seg000:0491 ; Returns:
seg000:0491 ;
seg000:0491 ;   DS:EAX - Pointer to the attribute's standard
seg000:0491 ;            attribute header. If the attribute was not
seg000:0491 ;            found, EAX is zero.
seg000:0491 ;
seg000:0491 ; Preserves/modifies:
seg000:0491 ;
seg000:0491 ;   (No explicit preservations)
seg000:0491
seg000:0491 FindAttribute   proc near
seg000:0491                 add     ax, [eax+NTFS_FILE_RECORD.FirstAttribOffset]
seg000:0495
seg000:0495 search_next:
seg000:0495                 cmp     [eaxSTD_ATTRIB_HDR.Type], -1
seg000:049A                 jz      not_found
seg000:049E                 cmp     [eax+STD_ATTRIB_HDR.Type], ebx
seg000:04A2                 jnz     next_attribute
seg000:04A6                 or      ecx, ecx
seg000:04A9                 jnz     find_named
seg000:04AD                 cmp     [eax+STD_ATTRIB_HDR.NameLength], 0
seg000:04B2                 jnz     next_attribute
seg000:04B6                 retn
seg000:04B7 ; ---------------------------------------------------------------------------
seg000:04B7
seg000:04B7 find_named:
seg000:04B7                 cmp     cl, [eax+STD_ATTRIB_HDR.NameLength]
seg000:04BB                 jnz     next_attribute
seg000:04BF                 mov     esi, eax
seg000:04C2                 add     si, [eax+STD_ATTRIB_HDR.NameOffset]
seg000:04C6                 call    UnicodeStringLwr
seg000:04C9                 push    ecx
seg000:04CB                 push    ds
seg000:04CC                 pop     es
seg000:04CD                 mov     edi, edx
seg000:04D0                 repe cmpsw
seg000:04D2                 pop     ecx
seg000:04D4                 jnz     next_attribute
seg000:04D8                 retn
seg000:04D9 ; ---------------------------------------------------------------------------
seg000:04D9
seg000:04D9 next_attribute:
seg000:04D9                 cmp     [eax+STD_ATTRIB_HDR.Length], 0
seg000:04DF                 jz      not_found
seg000:04E3                 add     eax, [eax+STD_ATTRIB_HDR.Length]
seg000:04E8                 jmp     short search_next
seg000:04EA ; ---------------------------------------------------------------------------
seg000:04EA
seg000:04EA not_found:
seg000:04EA                 sub     eax, eax
seg000:04ED                 retn
seg000:04ED FindAttribute   endp
seg000:04ED
seg000:04EE
seg000:04EE ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:04EE
seg000:04EE ; Description:
seg000:04EE ;
seg000:04EE ;   Finds the specified file's index entry in the given
seg000:04EE ;   index buffer.
seg000:04EE ;
seg000:04EE ; Arguments:
seg000:04EE ;
seg000:04EE ;   DS:EAX - Pointer to the index buffer header.
seg000:04EE ;
seg000:04EE ;   DS:EBX - Pointer to the filename.
seg000:04EE ;
seg000:04EE ;   ECX - Length of the filename.
seg000:04EE ;
seg000:04EE ; Returns:
seg000:04EE ;
seg000:04EE ;   DS:EAX - Pointer to the file's index entry. If the
seg000:04EE ;            file index entry was not found, EAX is zero.
seg000:04EE ;
seg000:04EE ; Preserves/modifies:
seg000:04EE ;
seg000:04EE ;   (No explicit preservations)
seg000:04EE
seg000:04EE FindFileIndexEntry proc near
seg000:04EE                 mov     esi, ebx
seg000:04F1                 call    UnicodeStringLwr
seg000:04F4                 add     eax, [eax+INDEX_HDR.FirstEntryOffset]
seg000:04F8
seg000:04F8 search_next:
seg000:04F8                 test    word ptr [eax+INDEX_ENTRY.Flags], 2
seg000:04FE                 jnz     entry_not_found
seg000:0502                 lea     edx, [eax+(size INDEX_ENTRY)]
seg000:0507                 cmp     cl, [edx+INDEX_ENTRY_FILENAME.FileNameLength]
seg000:050B                 jnz     next_entry
seg000:050F                 lea     esi, [edx+INDEX_ENTRY_FILENAME.FileName]
seg000:0514                 call    UnicodeStringLwr
seg000:0517                 push    ecx
seg000:0519                 push    ds
seg000:051A                 pop     es
seg000:051B                 mov     edi, ebx
seg000:051E                 repe cmpsw
seg000:0520                 pop     ecx
seg000:0522                 jnz     next_entry
seg000:0526                 retn
seg000:0527 ; ---------------------------------------------------------------------------
seg000:0527
seg000:0527 next_entry:
seg000:0527                 cmp     [eax+INDEX_ENTRY.IndexEntryLength], 0
seg000:052C                 jz      entry_not_found
seg000:0530                 add     ax, [eax+INDEX_ENTRY.IndexEntryLength]
seg000:0534                 jmp     short search_next
seg000:0536 ; ---------------------------------------------------------------------------
seg000:0536
seg000:0536 entry_not_found:
seg000:0536                 xor     eax, eax
seg000:0539                 retn
seg000:0539 FindFileIndexEntry endp
seg000:0539
seg000:053A
seg000:053A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:053A
seg000:053A ; Description:
seg000:053A ;
seg000:053A ;   Retrieves the specified attribute's data.
seg000:053A ;
seg000:053A ; Arguments:
seg000:053A ;
seg000:053A ;   DS:EBX - Pointer to the attribute's standard
seg000:053A ;            attribute header.
seg000:053A ;
seg000:053A ;   ES:EDI - Memory buffer for the attribute's data.
seg000:053A ;
seg000:053A ; Returns:
seg000:053A ;
seg000:053A ;   (No return value)
seg000:053A ;
seg000:053A ; Preserves/modifies:
seg000:053A ;
seg000:053A ;   (No explicit preservations)
seg000:053A
seg000:053A GetAttributeData proc near
seg000:053A                 cmp     [ebx+STD_ATTRIB_HDR.NonresidentFlag], 0
seg000:053F                 jnz     is_non_resident
seg000:0543                 push    es
seg000:0544                 push    ds
seg000:0545                 pushad
seg000:0547                 lea     edx, [ebx+(size STD_ATTRIB_HDR)]
seg000:054C                 mov     ecx, [edx+ATTRIB_HDR_RESIDENT.AttributeLength]
seg000:0550                 mov     esi, ebx
seg000:0553                 add     si, [edx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:0557                 rep movsb
seg000:0559                 popad
seg000:055B                 nop
seg000:055C                 pop     ds
seg000:055D                 pop     es
seg000:055E                 retn
seg000:055F ; ---------------------------------------------------------------------------
seg000:055F
seg000:055F is_non_resident:
seg000:055F                 lea     edx, [ebx+(size STD_ATTRIB_HDR)]
seg000:0564                 mov     ecx, dword ptr [edx+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0569                 inc     ecx
seg000:056B                 sub     eax, eax
seg000:056E                 call    ReadAttribDataClusters
seg000:0571                 retn
seg000:0571 GetAttributeData endp
seg000:0571
seg000:0572
seg000:0572 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0572
seg000:0572 ; Description:
seg000:0572 ;
seg000:0572 ;   Reads the specified number of clusters from the
seg000:0572 ;   specified virtual cluster number from the specified
seg000:0572 ;   attribute's data. The attribute must be non-resident.
seg000:0572 ;
seg000:0572 ; Arguments:
seg000:0572 ;
seg000:0572 ;   DS:EBX - Pointer to the attribute's standard
seg000:0572 ;            attribute header. The attribute must be
seg000:0572 ;            non-resident.
seg000:0572 ;
seg000:0572 ;   EAX - Virtual cluster number to read from.
seg000:0572 ;
seg000:0572 ;   ECX - Number of clusters to read.
seg000:0572 ;
seg000:0572 ;   ES:EDI - Memory buffer for the attribute's data to
seg000:0572 ;            be read.
seg000:0572 ;
seg000:0572 ; Returns:
seg000:0572 ;
seg000:0572 ;   (No return value. Errors produce a fatal error
seg000:0572 ;   display message.)
seg000:0572 ;
seg000:0572 ; Preserves/modifies:
seg000:0572 ;
seg000:0572 ;   Preserves 32-bit GP registers, DS, ES.
seg000:0572
seg000:0572 ReadAttribDataClusters proc near
seg000:0572                 push    es
seg000:0573                 push    ds
seg000:0574                 pushad
seg000:0576                 cmp     [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:057B                 jz      check_more_data
seg000:057F                 jmp     disk_read_error
seg000:0582 ; ---------------------------------------------------------------------------
seg000:0582
seg000:0582 check_more_data:
seg000:0582                 cmp     ecx, 0
seg000:0586                 jnz     read_more_data
seg000:058A                 popad
seg000:058C                 nop
seg000:058D                 pop     ds
seg000:058E                 pop     es
seg000:058F                 retn
seg000:0590 ; ---------------------------------------------------------------------------
seg000:0590
seg000:0590 read_more_data:
seg000:0590                 push    ebx
seg000:0592                 push    eax
seg000:0594                 push    ecx
seg000:0596                 push    edi
seg000:0598                 push    es
seg000:0599                 call    GetLcnOfAttrDataVcn
seg000:059C                 mov     edx, ecx
seg000:059F                 pop     es
seg000:05A0                 pop     edi
seg000:05A2                 pop     ecx
seg000:05A4                 cmp     ecx, edx
seg000:05A7                 jge     @@1
seg000:05AB                 mov     edx, ecx
seg000:05AE
seg000:05AE @@1:
seg000:05AE                 call    ReadDiskClusters
seg000:05B1                 sub     ecx, edx
seg000:05B4                 mov     ebx, edx
seg000:05B7                 mov     eax, edx
seg000:05BA                 movzx   edx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:05C0                 mul     edx
seg000:05C3                 movzx   edx, ds:NtfsBpbEbpb.BytesPerSector
seg000:05C9                 mul     edx
seg000:05CC                 add     edi, eax
seg000:05CF                 pop     eax
seg000:05D1                 add     eax, ebx
seg000:05D4                 pop     ebx
seg000:05D6                 jmp     short check_more_data
seg000:05D6 ReadAttribDataClusters endp
seg000:05D6
seg000:05D8
seg000:05D8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:05D8
seg000:05D8 ; Description:
seg000:05D8 ;
seg000:05D8 ;   Reads the specified number of sectors from the
seg000:05D8 ;   specified virtual sector number from the specified
seg000:05D8 ;   attribute's data. The attribute must be non-resident.
seg000:05D8 ;
seg000:05D8 ; Arguments:
seg000:05D8 ;
seg000:05D8 ;   DS:EBX - Pointer to the attribute's standard
seg000:05D8 ;            attribute header. The attribute must be
seg000:05D8 ;            non-resident.
seg000:05D8 ;
seg000:05D8 ;   EAX - Virtual sector number to read from.
seg000:05D8 ;
seg000:05D8 ;   ECX - Number of sectors to read.
seg000:05D8 ;
seg000:05D8 ;   ES:EDI - Memory buffer for the attribute's data to
seg000:05D8 ;            be read.
seg000:05D8 ;
seg000:05D8 ; Returns:
seg000:05D8 ;
seg000:05D8 ;   (No return value. Errors produce a fatal error
seg000:05D8 ;   display message.)
seg000:05D8 ;
seg000:05D8 ; Preserves/modifies:
seg000:05D8 ;
seg000:05D8 ;   Preserves 32-bit GP registers, DS, ES.
seg000:05D8
seg000:05D8 ReadAttribDataSectors proc far
seg000:05D8                 push    es
seg000:05D9                 push    ds
seg000:05DA                 pushad
seg000:05DC                 cmp     [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:05E1                 jz      check_more_data
seg000:05E5                 jmp     disk_read_error
seg000:05E8 ; ---------------------------------------------------------------------------
seg000:05E8
seg000:05E8 check_more_data:
seg000:05E8                 cmp     ecx, 0
seg000:05EC                 jnz     read_more_data
seg000:05F0                 popad
seg000:05F2                 nop
seg000:05F3                 pop     ds
seg000:05F4                 pop     es
seg000:05F5                 retn
seg000:05F6 ; ---------------------------------------------------------------------------
seg000:05F6
seg000:05F6 read_more_data:
seg000:05F6                 push    ebx
seg000:05F8                 push    eax
seg000:05FA                 push    ecx
seg000:05FC                 push    edi
seg000:05FE                 push    es
seg000:05FF                 push    ecx
seg000:0601                 xor     edx, edx
seg000:0604                 movzx   ecx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:060A                 div     ecx
seg000:060D                 push    edx
seg000:060F                 call    GetLcnOfAttrDataVcn
seg000:0612                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0618                 mul     ebx
seg000:061B                 pop     edx
seg000:061D                 add     eax, edx
seg000:0620                 push    eax
seg000:0622                 movzx   eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0628                 mul     ecx
seg000:062B                 mov     edx, eax
seg000:062E                 pop     eax
seg000:0630                 pop     ecx
seg000:0632                 pop     es
seg000:0633                 pop     edi
seg000:0635                 pop     ecx
seg000:0637                 cmp     ecx, edx
seg000:063A                 jge     @@1
seg000:063E                 mov     edx, ecx
seg000:0641
seg000:0641 @@1:
seg000:0641                 mov     ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0645                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, dx
seg000:0649                 push    es
seg000:064A                 push    ds
seg000:064B                 pushad
seg000:064D                 mov     bx, di
seg000:064F                 and     bx, 0Fh
seg000:0652                 mov     ax, es
seg000:0654                 shr     edi, 4
seg000:0658                 add     ax, di
seg000:065A                 push    ax
seg000:065B                 pop     es
seg000:065C                 call    ReadDiskSectors
seg000:065F                 popad
seg000:0661                 nop
seg000:0662                 pop     ds
seg000:0663                 pop     es
seg000:0664                 sub     ecx, edx
seg000:0667                 mov     ebx, edx
seg000:066A                 mov     eax, edx
seg000:066D                 movzx   edx, ds:NtfsBpbEbpb.BytesPerSector
seg000:0673                 mul     edx
seg000:0676                 add     edi, eax
seg000:0679                 pop     eax
seg000:067B                 add     eax, ebx
seg000:067E                 pop     ebx
seg000:0680                 jmp     check_more_data
seg000:0680 ReadAttribDataSectors endp
seg000:0680
seg000:0683
seg000:0683 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0683
seg000:0683 ; Description:
seg000:0683 ;
seg000:0683 ;   Restores the given file record segment from fixups
seg000:0683 ;   in the record's update sequence array.
seg000:0683 ;
seg000:0683 ; Arguments:
seg000:0683 ;
seg000:0683 ;   DS:EDI - Pointer to the file record segment.
seg000:0683 ;
seg000:0683 ; Returns:
seg000:0683 ;
seg000:0683 ;   (No return value. Errors produce a fatal error
seg000:0683 ;   display message.)
seg000:0683 ;
seg000:0683 ; Preserves/modifies:
seg000:0683 ;
seg000:0683 ;     Preserves 32-bit GP registers, DS, ES.
seg000:0683
seg000:0683 RestoreRecordFixups proc near
seg000:0683                 push    es
seg000:0684                 push    ds
seg000:0685                 pushad
seg000:0687                 movzx   ebx, es:[edi+NTFS_FILE_RECORD.UpdateSequenceOffset]
seg000:068E                 movzx   ecx, es:[edi+NTFS_FILE_RECORD.UpdateSequenceSize]
seg000:0695                 or      ecx, ecx
seg000:0698                 jz      disk_read_error
seg000:069C                 add     ebx, edi
seg000:069F                 add     ebx, 2
seg000:06A3                 add     edi, 1FEh
seg000:06AA                 dec     ecx
seg000:06AC
seg000:06AC loop:
seg000:06AC                 or      ecx, ecx
seg000:06AF                 jz      done
seg000:06B3                 mov     ax, es:[ebx]
seg000:06B7                 mov     es:[edi], ax
seg000:06BB                 add     ebx, 2
seg000:06BF                 add     edi, 200h
seg000:06C6                 dec     ecx
seg000:06C8                 jmp     short loop
seg000:06CA ; ---------------------------------------------------------------------------
seg000:06CA
seg000:06CA done:
seg000:06CA                 popad
seg000:06CC                 nop
seg000:06CD                 pop     ds
seg000:06CE                 pop     es
seg000:06CF                 retn
seg000:06CF RestoreRecordFixups endp
seg000:06CF
seg000:06D0
seg000:06D0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:06D0
seg000:06D0 ; Description:
seg000:06D0 ;
seg000:06D0 ;   Initializes a data structure that is used for
seg000:06D0 ;   accessing the contents of the MFT (i.e. file records,
seg000:06D0 ;   stored in the $MFT file's unnamed $DATA attribute
seg000:06D0 ;   stream). The structure contains the $MFT base file
seg000:06D0 ;   record segment, a file record segment buffer for use
seg000:06D0 ;   in reading other $MFT file record segments (also
seg000:06D0 ;   known as record extents), and a run-list describing
seg000:06D0 ;   the location and size of each fragment of every file
seg000:06D0 ;   record segment that makes up the $MFT file record
seg000:06D0 ;   (i.e. the base file record and all file record
seg000:06D0 ;   extents).
seg000:06D0 ;
seg000:06D0 ; Arguments:
seg000:06D0 ;
seg000:06D0 ;   (None)
seg000:06D0 ;
seg000:06D0 ; Returns:
seg000:06D0 ;
seg000:06D0 ;   (No return value. Errors produce a fatal error
seg000:06D0 ;   display message.)
seg000:06D0 ;
seg000:06D0 ; Preserves/modifies:
seg000:06D0 ;
seg000:06D0 ;   Preserves 32-bit GP registers, DS, ES.
seg000:06D0
seg000:06D0 MftFrInitialize proc near
seg000:06D0                 push    es
seg000:06D1                 push    ds
seg000:06D2                 pushad
seg000:06D4                 mov     eax, 1
seg000:06DA                 mov     ds:MftFrsCount, eax
seg000:06DE                 mov     eax, ds:pMftBfrs
seg000:06E2                 add     eax, ds:BytesPerFrs
seg000:06E7                 mov     ds:pMftFrInfo, eax
seg000:06EB                 add     eax, ds:BytesPerFrs
seg000:06F0                 mov     ds:pMftFrInfoEnd, eax
seg000:06F4                 mov     eax, dword ptr ds:NtfsBpbEbpb.LcnOfMftBfrs
seg000:06F8                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:06FE                 mul     ebx
seg000:0701                 mov     ebx, ds:pMftFrInfoEnd
seg000:0706                 mov     [bx], eax
seg000:0709                 mov     ds:NtfsBpbEbpb.LsnToRead, eax
seg000:070D                 add     bx, 4
seg000:0710                 mov     eax, ds:SectorsPerFrs
seg000:0714                 mov     [bx], eax
seg000:0717                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:071A                 add     bx, 4
seg000:071D                 mov     ds:pMftFrInfoEnd, ebx
seg000:0722                 mov     ebx, ds:pMftBfrs
seg000:0727                 push    ds
seg000:0728                 pop     es
seg000:0729                 call    ReadDiskSectors
seg000:072C                 mov     edi, ebx
seg000:072F                 call    RestoreRecordFixups
seg000:0732                 mov     eax, ds:pMftBfrs
seg000:0736                 mov     ebx, $ATTRIBUTE_LIST
seg000:073C                 mov     ecx, 0
seg000:0742                 mov     edx, 0
seg000:0748                 call    FindAttribute
seg000:074B                 or      eax, eax
seg000:074E                 jz      return
seg000:0752                 mov     ebx, eax
seg000:0755                 push    ds
seg000:0756                 pop     es
seg000:0757                 mov     edi, ds:pAttribListData
seg000:075C                 call    GetAttributeData
seg000:075F                 mov     ebx, ds:pAttribListData
seg000:0764
seg000:0764 find_first_data:
seg000:0764                 cmp     [bx+STD_ATTRIB_HDR.Type], $DATA
seg000:076B                 jz      find_next_data
seg000:076F                 add     bx, word ptr [bx+STD_ATTRIB_HDR.Length]
seg000:0772                 jmp     short find_first_data
seg000:0774 ; ---------------------------------------------------------------------------
seg000:0774
seg000:0774 add_segment_to_runlist:
seg000:0774                 push    ebx
seg000:0776                 mov     eax, dword ptr [bx+ATTRIB_LIST_ENTRY.BaseFileReference]
seg000:077A                 mul     ds:SectorsPerFrs
seg000:077F                 push    eax
seg000:0781                 xor     edx, edx
seg000:0784                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:078A                 div     ebx
seg000:078D                 push    edx
seg000:078F                 call    GetLcnOfMftVcn
seg000:0792                 or      eax, eax
seg000:0795                 jz      disk_read_error
seg000:0799                 mov     ecx, ds:SectorsPerFrs
seg000:079E                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07A4                 mul     ebx
seg000:07A7                 pop     edx
seg000:07A9                 add     eax, edx
seg000:07AC                 mov     ebx, ds:pMftFrInfoEnd
seg000:07B1                 mov     [bx], eax
seg000:07B4                 add     bx, 4
seg000:07B7                 movzx   eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07BD                 sub     eax, edx
seg000:07C0                 cmp     eax, ecx
seg000:07C3                 jbe     @@1
seg000:07C7                 mov     eax, ecx
seg000:07CA
seg000:07CA @@1:
seg000:07CA                 mov     [bx], eax
seg000:07CD
seg000:07CD check_segment_is_complete:
seg000:07CD                 sub     ecx, eax
seg000:07D0                 pop     edx
seg000:07D2                 jz      segment_is_complete
seg000:07D6                 add     eax, edx
seg000:07D9                 push    eax
seg000:07DB                 xor     edx, edx
seg000:07DE                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07E4                 div     ebx
seg000:07E7                 push    ecx
seg000:07E9                 call    GetLcnOfMftVcn
seg000:07EC                 pop     ecx
seg000:07EE                 or      eax, eax
seg000:07F1                 jz      disk_read_error
seg000:07F5                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07FB                 mul     ebx
seg000:07FE                 mov     ebx, ds:pMftFrInfoEnd
seg000:0803                 mov     edx, [bx]
seg000:0806                 add     bx, 4
seg000:0809                 add     edx, [bx]
seg000:080C                 cmp     edx, eax
seg000:080F                 jnz     fragment_is_noncontiguous
seg000:0813                 movzx   eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0819                 cmp     eax, ecx
seg000:081C                 jbe     @@2
seg000:0820                 mov     eax, ecx
seg000:0823
seg000:0823 @@2:
seg000:0823                 add     [bx], eax
seg000:0826                 jmp     short check_segment_is_complete
seg000:0828 ; ---------------------------------------------------------------------------
seg000:0828
seg000:0828 fragment_is_noncontiguous:
seg000:0828                 add     bx, 4
seg000:082B                 mov     ds:pMftFrInfoEnd, ebx
seg000:0830                 mov     [bx], eax
seg000:0833                 add     bx, 4
seg000:0836                 movzx   eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:083C                 cmp     eax, ecx
seg000:083F                 jbe     @@3
seg000:0843                 mov     eax, ecx
seg000:0846
seg000:0846 @@3:
seg000:0846                 mov     [bx], eax
seg000:0849                 jmp     short check_segment_is_complete
seg000:084B ; ---------------------------------------------------------------------------
seg000:084B
seg000:084B segment_is_complete:
seg000:084B                 add     bx, 4
seg000:084E                 inc     ds:MftFrsCount
seg000:0853                 mov     ds:pMftFrInfoEnd, ebx
seg000:0858                 pop     ebx
seg000:085A
seg000:085A find_next_data:
seg000:085A                 add     bx, word ptr [bx+STD_ATTRIB_HDR.Length]
seg000:085D                 cmp     [bx+STD_ATTRIB_HDR.Type], $DATA
seg000:0864                 jz      add_segment_to_runlist
seg000:0868
seg000:0868 return:
seg000:0868                 popad
seg000:086A                 nop
seg000:086B                 pop     ds
seg000:086C                 pop     es
seg000:086D                 retn
seg000:086D MftFrInitialize endp
seg000:086D
seg000:086E
seg000:086E ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:086E
seg000:086E ; Description:
seg000:086E ;
seg000:086E ;   Translates the specified virtual cluster number in
seg000:086E ;   the MFT to its corresponding logical cluster number.
seg000:086E ;   Additionally reports the number of contiguous
seg000:086E ;   clusters available at this logical cluster.
seg000:086E ;
seg000:086E ; Arguments:
seg000:086E ;
seg000:086E ;   EAX - Virtual cluster number in the MFT.
seg000:086E ;
seg000:086E ; Returns:
seg000:086E ;
seg000:086E ;   EAX - The logical cluster number corresponding to
seg000:086E ;         the specified virtual cluster number in the
seg000:086E ;         MFT. If the virtual cluster number is invalid
seg000:086E ;         then EAX is zero.
seg000:086E ;         (Errors produce a fatal error display message.)
seg000:086E ;
seg000:086E ;   ECX - The number of contiguous clusters available at
seg000:086E ;         this logical cluster. (Only valid if the
seg000:086E ;         virtual cluster number was valid.)
seg000:086E ;
seg000:086E ; Preserves/modifies:
seg000:086E ;
seg000:086E ;   (No explicit preservations)
seg000:086E
seg000:086E GetLcnOfMftVcn  proc near
seg000:086E                 mov     edx, eax
seg000:0871                 mov     ecx, ds:MftFrsCount
seg000:0876                 mov     esi, ds:pMftFrInfo
seg000:087B                 add     esi, ds:BytesPerFrs
seg000:0880
seg000:0880 search_next_segment:
seg000:0880                 push    edx
seg000:0882                 push    ecx
seg000:0884                 push    edx
seg000:0886                 mov     ebx, ds:pMftFrInfo
seg000:088B                 mov     edi, ds:SectorsPerFrs
seg000:0890
seg000:0890 read_segment_fragment:
seg000:0890                 mov     eax, [si]
seg000:0893                 mov     ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0897                 add     si, 4
seg000:089A                 mov     eax, [si]
seg000:089D                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:08A0                 add     si, 4
seg000:08A3                 push    ds
seg000:08A4                 pop     es
seg000:08A5                 call    ReadDiskSectors
seg000:08A8                 sub     edi, eax
seg000:08AB                 jz      check_record_segment
seg000:08AF                 mul     ds:NtfsBpbEbpb.BytesPerSector
seg000:08B3                 add     bx, ax
seg000:08B5                 jmp     short read_segment_fragment
seg000:08B7 ; ---------------------------------------------------------------------------
seg000:08B7
seg000:08B7 check_record_segment:
seg000:08B7                 mov     edi, ds:pMftFrInfo
seg000:08BC                 push    ds
seg000:08BD                 pop     es
seg000:08BE                 call    RestoreRecordFixups
seg000:08C1                 mov     eax, ds:pMftFrInfo
seg000:08C5                 mov     ebx, $DATA
seg000:08CB                 mov     ecx, 0
seg000:08D1                 mov     edx, ecx
seg000:08D4                 call    FindAttribute
seg000:08D7                 or      eax, eax
seg000:08DA                 jz      disk_read_error
seg000:08DE                 mov     ebx, eax
seg000:08E1                 pop     eax
seg000:08E3                 push    esi
seg000:08E5                 call    GetLcnOfAttrDataVcn
seg000:08E8                 pop     esi
seg000:08EA                 or      eax, eax
seg000:08ED                 jz      not_found_in_segment
seg000:08F1                 pop     ebx
seg000:08F3                 pop     ebx
seg000:08F5                 retn
seg000:08F6 ; ---------------------------------------------------------------------------
seg000:08F6
seg000:08F6 not_found_in_segment:
seg000:08F6                 pop     ecx
seg000:08F8                 pop     edx
seg000:08FA                 loop    search_next_segment
seg000:08FC                 xor     eax, eax
seg000:08FF                 retn
seg000:08FF GetLcnOfMftVcn  endp
seg000:08FF
seg000:0900
seg000:0900 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0900
seg000:0900 ; Description:
seg000:0900 ;
seg000:0900 ;   Reads the specified number of sectors from the
seg000:0900 ;   specified virtual sector number in the MFT.
seg000:0900 ;
seg000:0900 ; Arguments:
seg000:0900 ;
seg000:0900 ;   EAX - Virtual sector number of the MFT data to read.
seg000:0900 ;
seg000:0900 ;   ECX - Number of sectors of the MFT data to read.
seg000:0900 ;
seg000:0900 ;   ES:EDI - Memory buffer for the sectors to be read.
seg000:0900 ;
seg000:0900 ; Returns:
seg000:0900 ;
seg000:0900 ;   (No return value. Errors produce a fatal error
seg000:0900 ;   display message.)
seg000:0900 ;
seg000:0900 ; Preserves/modifies:
seg000:0900 ;
seg000:0900 ;   Preserves 32-bit GP registers, DS, ES.
seg000:0900
seg000:0900 GetMftData      proc near
seg000:0900                 push    es
seg000:0901                 push    ds
seg000:0902                 pushad
seg000:0904
seg000:0904 read_more_data:
seg000:0904                 push    eax
seg000:0906                 push    ecx
seg000:0908                 xor     edx, edx
seg000:090B                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0911                 div     ebx
seg000:0914                 push    edx
seg000:0916                 push    edi
seg000:0918                 call    GetLcnOfMftVcn
seg000:091B                 pop     edi
seg000:091D                 or      eax, eax
seg000:0920                 jz      disk_read_error
seg000:0924                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:092A                 mul     ebx
seg000:092D                 pop     edx
seg000:092F                 add     eax, edx
seg000:0932                 mov     ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0936                 pop     ecx
seg000:0938                 movzx   ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:093E                 cmp     ecx, ebx
seg000:0941                 jle     @@1
seg000:0945                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, bx
seg000:0949                 sub     ecx, ebx
seg000:094C                 pop     eax
seg000:094E                 add     eax, ebx
seg000:0951                 push    eax
seg000:0953                 push    ecx
seg000:0955                 jmp     short read_data_sectors
seg000:0957 ; ---------------------------------------------------------------------------
seg000:0957                 nop
seg000:0958
seg000:0958 @@1:
seg000:0958                 pop     eax
seg000:095A                 add     eax, ecx
seg000:095D                 push    eax
seg000:095F                 mov     ds:NtfsBpbEbpb.NoOfSectorsToRead, cx
seg000:0963                 mov     ecx, 0
seg000:0969                 push    ecx
seg000:096B
seg000:096B read_data_sectors:
seg000:096B                 push    es
seg000:096C                 push    edi
seg000:096E                 mov     bx, di
seg000:0970                 and     bx, 0Fh
seg000:0973                 mov     ax, es
seg000:0975                 shr     edi, 4
seg000:0979                 add     ax, di
seg000:097B                 push    ax
seg000:097C                 pop     es
seg000:097D                 call    ReadDiskSectors
seg000:0980                 pop     edi
seg000:0982                 pop     es
seg000:0983                 add     edi, ds:BytesPerCluster
seg000:0988                 pop     ecx
seg000:098A                 pop     eax
seg000:098C                 cmp     ecx, 0
seg000:0990                 jg      read_more_data
seg000:0994                 popad
seg000:0996                 nop
seg000:0997                 pop     ds
seg000:0998                 pop     es
seg000:0999                 retn
seg000:0999 GetMftData      endp
seg000:0999
seg000:099A
seg000:099A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:099A
seg000:099A ; Description:
seg000:099A ;
seg000:099A ;   Retrieves the specified file record segment from the
seg000:099A ;   MFT.
seg000:099A ;
seg000:099A ; Arguments:
seg000:099A ;
seg000:099A ;   EAX - File record number.
seg000:099A ;
seg000:099A ;   ES:EDI - Memory buffer for the file record segment.
seg000:099A ;
seg000:099A ; Returns:
seg000:099A ;
seg000:099A ;   (No return value)
seg000:099A ;
seg000:099A ; Preserves/modifies:
seg000:099A ;
seg000:099A ;   Preserves 32-bit GP registers, DS, ES.
seg000:099A
seg000:099A GetFileRecord   proc near
seg000:099A                 push    es
seg000:099B                 push    ds
seg000:099C                 pushad
seg000:099E                 mul     ds:SectorsPerFrs
seg000:09A3                 mov     ecx, ds:SectorsPerFrs
seg000:09A8                 call    GetMftData
seg000:09AB                 call    RestoreRecordFixups
seg000:09AE                 popad
seg000:09B0                 nop
seg000:09B1                 pop     ds
seg000:09B2                 pop     es
seg000:09B3                 retn
seg000:09B3 GetFileRecord   endp
seg000:09B3
seg000:09B4
seg000:09B4 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:09B4
seg000:09B4 ; Description:
seg000:09B4 ;
seg000:09B4 ;   Retrieves the specified index allocation entry.
seg000:09B4 ;
seg000:09B4 ; Arguments:
seg000:09B4 ;
seg000:09B4 ;   EAX - Index allocation entry number.
seg000:09B4 ;
seg000:09B4 ; Returns:
seg000:09B4 ;
seg000:09B4 ;   (No return value)
seg000:09B4 ;
seg000:09B4 ; Preserves/modifies:
seg000:09B4 ;
seg000:09B4 ;   Preserves 32-bit GP registers, DS, ES.
seg000:09B4
seg000:09B4 GetIndexAllocEntry proc near
seg000:09B4                 push    es
seg000:09B5                 push    ds
seg000:09B6                 pushad
seg000:09B8                 mul     ds:SectorsPerIaEntry
seg000:09BD                 mov     ebx, ds:pIndexAllocHdr
seg000:09C2                 mov     ecx, ds:SectorsPerIaEntry
seg000:09C7                 push    ds
seg000:09C8                 pop     es
seg000:09C9                 mov     edi, ds:pIndexAllocEntry
seg000:09CE                 call    near ptr ReadAttribDataSectors
seg000:09D1                 call    RestoreRecordFixups
seg000:09D4                 popad
seg000:09D6                 nop
seg000:09D7                 pop     ds
seg000:09D8                 pop     es
seg000:09D9                 retn
seg000:09D9 GetIndexAllocEntry endp
seg000:09D9
seg000:09DA
seg000:09DA ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:09DA
seg000:09DA ; Description:
seg000:09DA ;
seg000:09DA ;   Checks whether or not the specified index allocation
seg000:09DA ;   entry is in use by querying the corresponding bit in
seg000:09DA ;   the allocation bitmap.
seg000:09DA ;
seg000:09DA ; Arguments:
seg000:09DA ;
seg000:09DA ;   EAX - Index allocation entry number.
seg000:09DA ;
seg000:09DA ; Returns:
seg000:09DA ;
seg000:09DA ;   Carry flag is CLEAR if the index allocation entry
seg000:09DA ;   is in use. It is SET if NOT in use.
seg000:09DA ;
seg000:09DA ; Preserves/modifies:
seg000:09DA ;
seg000:09DA ;   Explicitly preserves EAX, EBX, ECX. No other 32-bit
seg000:09DA ;   GP registers modified. No segment registers modified.
seg000:09DA ;
seg000:09DA
seg000:09DA CheckIaEntryIsInUse proc near
seg000:09DA                 push    eax
seg000:09DC                 push    ebx
seg000:09DE                 push    ecx
seg000:09E0                 mov     ebx, ds:pBitmapData
seg000:09E5                 mov     ecx, eax
seg000:09E8                 shr     eax, 3
seg000:09EC                 and     ecx, 7
seg000:09F0                 add     ebx, eax
seg000:09F3                 mov     eax, 1
seg000:09F9                 shl     eax, cl
seg000:09FC                 test    [ebx], al
seg000:09FF                 jz      not_in_use
seg000:0A03                 clc
seg000:0A04                 jmp     short return
seg000:0A06 ; ---------------------------------------------------------------------------
seg000:0A06                 nop
seg000:0A07
seg000:0A07 not_in_use:
seg000:0A07                 stc
seg000:0A08
seg000:0A08 return:
seg000:0A08                 pop     ecx
seg000:0A0A                 pop     ebx
seg000:0A0C                 pop     eax
seg000:0A0E                 retn
seg000:0A0E CheckIaEntryIsInUse endp
seg000:0A0E
seg000:0A0F
seg000:0A0F ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0A0F
seg000:0A0F ; Description:
seg000:0A0F ;
seg000:0A0F ;   Translates the specified virtual cluster number in
seg000:0A0F ;   the specified attribute's data to its corresponding
seg000:0A0F ;   logical cluster number. Additionally reports the
seg000:0A0F ;   number of contiguous clusters available at this
seg000:0A0F ;   logical cluster. The attribute must be non-resident.
seg000:0A0F ;
seg000:0A0F ; Arguments:
seg000:0A0F ;
seg000:0A0F ;   DS:EBX - Pointer to the attribute's standard
seg000:0A0F ;            attribute header. The attribute must be
seg000:0A0F ;            non-resident.
seg000:0A0F ;
seg000:0A0F ;   EAX - Virtual cluster number in the attribute's data.
seg000:0A0F ;
seg000:0A0F ; Returns:
seg000:0A0F ;
seg000:0A0F ;   EAX - The logical cluster number corresponding to
seg000:0A0F ;         the specified virtual cluster number in the
seg000:0A0F ;         attribute's data. If the virtual cluster
seg000:0A0F ;         number is invalid then EAX is zero.
seg000:0A0F ;
seg000:0A0F ;   ECX - The number of contiguous clusters available at
seg000:0A0F ;         this logical cluster. (Only valid if the
seg000:0A0F ;         virtual cluster number was valid.)
seg000:0A0F ;
seg000:0A0F ; Preserves/modifies:
seg000:0A0F ;
seg000:0A0F ;   (No explicit preservations)
seg000:0A0F
seg000:0A0F GetLcnOfAttrDataVcn proc near
seg000:0A0F                 cmp     [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:0A14                 jz      is_non_resident
seg000:0A18                 sub     eax, eax
seg000:0A1B                 retn
seg000:0A1C ; ---------------------------------------------------------------------------
seg000:0A1C
seg000:0A1C is_non_resident:
seg000:0A1C                 lea     esi, [ebx+(size STD_ATTRIB_HDR)]
seg000:0A21                 mov     edx, dword ptr [esi+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0A26                 cmp     eax, edx
seg000:0A29                 ja      vcn_out_of_range
seg000:0A2D                 mov     edx, dword ptr [esi+ATTRIB_HDR_NONRESIDENT.StartingVcn]
seg000:0A31                 cmp     eax, edx
seg000:0A34                 jnb     @@1
seg000:0A38
seg000:0A38 vcn_out_of_range:
seg000:0A38                 sub     eax, eax
seg000:0A3B                 retn
seg000:0A3C ; ---------------------------------------------------------------------------
seg000:0A3C
seg000:0A3C @@1:
seg000:0A3C                 add     bx, [esi+ATTRIB_HDR_NONRESIDENT.DataRunsOffset]
seg000:0A40                 sub     esi, esi
seg000:0A43
seg000:0A43 next_data_run:
seg000:0A43                 cmp     byte ptr [ebx], 0
seg000:0A47                 jz      error_end_of_data_runs
seg000:0A4B                 call    GetDataRunOffset
seg000:0A4E                 add     esi, ecx
seg000:0A51                 call    GetDataRunLength
seg000:0A54                 add     ecx, edx
seg000:0A57                 cmp     eax, ecx
seg000:0A5A                 jl      found_data_run_for_vcn
seg000:0A5E                 mov     edx, ecx
seg000:0A61                 push    eax
seg000:0A63                 movzx   ecx, byte ptr [ebx]
seg000:0A68                 mov     eax, ecx
seg000:0A6B                 and     eax, 0Fh
seg000:0A6F                 shr     ecx, 4
seg000:0A73                 add     ebx, ecx
seg000:0A76                 add     ebx, eax
seg000:0A79                 inc     ebx
seg000:0A7B                 pop     eax
seg000:0A7D                 jmp     short next_data_run
seg000:0A7F ; ---------------------------------------------------------------------------
seg000:0A7F
seg000:0A7F found_data_run_for_vcn:
seg000:0A7F                 sub     ecx, eax
seg000:0A82                 sub     eax, edx
seg000:0A85                 add     eax, esi
seg000:0A88                 retn
seg000:0A89 ; ---------------------------------------------------------------------------
seg000:0A89
seg000:0A89 error_end_of_data_runs:
seg000:0A89                 sub     eax, eax
seg000:0A8C                 retn
seg000:0A8C GetLcnOfAttrDataVcn endp
seg000:0A8C
seg000:0A8D
seg000:0A8D ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0A8D
seg000:0A8D ; Description:
seg000:0A8D ;
seg000:0A8D ;   Retrieves the data run length value from the
seg000:0A8D ;   given data run.
seg000:0A8D ;
seg000:0A8D ; Arguments:
seg000:0A8D ;
seg000:0A8D ;   DS:EBX - Pointer to the data run.
seg000:0A8D ;
seg000:0A8D ; Returns:
seg000:0A8D ;
seg000:0A8D ;   ECX - Data run length value. If the value could not
seg000:0A8D ;         be retrieved then ECX is zero.
seg000:0A8D ;
seg000:0A8D ; Preserves/modifies:
seg000:0A8D ;
seg000:0A8D ;   Explicitly preserves EBX, EDX. No other 32-bit
seg000:0A8D ;   GP registers modified. No segment registers modified.
seg000:0A8D ;
seg000:0A8D
seg000:0A8D GetDataRunLength proc near
seg000:0A8D                 sub     ecx, ecx
seg000:0A90                 mov     cl, [ebx]
seg000:0A93                 and     cl, 0Fh
seg000:0A96                 cmp     ecx, 0
seg000:0A9A                 jnz     get_length_value
seg000:0A9E                 sub     ecx, ecx
seg000:0AA1                 retn
seg000:0AA2 ; ---------------------------------------------------------------------------
seg000:0AA2
seg000:0AA2 get_length_value:
seg000:0AA2                 push    ebx
seg000:0AA4                 push    edx
seg000:0AA6                 add     ebx, ecx
seg000:0AA9                 movsx   edx, byte ptr [ebx]
seg000:0AAE                 dec     ecx
seg000:0AB0                 dec     ebx
seg000:0AB2
seg000:0AB2 loop:
seg000:0AB2                 cmp     ecx, 0
seg000:0AB6                 jz      have_length_value
seg000:0ABA                 shl     edx, 8
seg000:0ABE                 mov     dl, [ebx]
seg000:0AC1                 dec     ebx
seg000:0AC3                 dec     ecx
seg000:0AC5                 jmp     short loop
seg000:0AC7 ; ---------------------------------------------------------------------------
seg000:0AC7
seg000:0AC7 have_length_value:
seg000:0AC7                 mov     ecx, edx
seg000:0ACA                 pop     edx
seg000:0ACC                 pop     ebx
seg000:0ACE                 retn
seg000:0ACE GetDataRunLength endp
seg000:0ACE
seg000:0ACF
seg000:0ACF ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0ACF
seg000:0ACF ; Description:
seg000:0ACF ;
seg000:0ACF ;   Retrieves the data run offset value from the
seg000:0ACF ;   given data run.
seg000:0ACF ;
seg000:0ACF ; Arguments:
seg000:0ACF ;
seg000:0ACF ;   DS:EBX - Pointer to the data run.
seg000:0ACF ;
seg000:0ACF ; Returns:
seg000:0ACF ;
seg000:0ACF ;   ECX - Data run offset value. If the value could not
seg000:0ACF ;         be retrieved then ECX is zero.
seg000:0ACF ;
seg000:0ACF ; Preserves/modifies:
seg000:0ACF ;
seg000:0ACF ;   Explicitly preserves EBX, EDX. No other 32-bit
seg000:0ACF ;   GP registers modified. No segment registers modified.
seg000:0ACF ;
seg000:0ACF
seg000:0ACF GetDataRunOffset proc near
seg000:0ACF                 push    ebx
seg000:0AD1                 push    edx
seg000:0AD3                 sub     edx, edx
seg000:0AD6                 mov     dl, [ebx]
seg000:0AD9                 and     edx, 0Fh
seg000:0ADD                 sub     ecx, ecx
seg000:0AE0                 mov     cl, [ebx]
seg000:0AE3                 shr     cl, 4
seg000:0AE6                 cmp     ecx, 0
seg000:0AEA                 jnz     get_offset_value
seg000:0AEE                 sub     ecx, ecx
seg000:0AF1                 pop     edx
seg000:0AF3                 pop     ebx
seg000:0AF5                 retn
seg000:0AF6 ; ---------------------------------------------------------------------------
seg000:0AF6
seg000:0AF6 get_offset_value:
seg000:0AF6                 add     ebx, edx
seg000:0AF9                 add     ebx, ecx
seg000:0AFC                 movsx   edx, byte ptr [ebx]
seg000:0B01                 dec     ecx
seg000:0B03                 dec     ebx
seg000:0B05
seg000:0B05 loop:
seg000:0B05                 cmp     ecx, 0
seg000:0B09                 jz      have_offset_value
seg000:0B0D                 shl     edx, 8
seg000:0B11                 mov     dl, [ebx]
seg000:0B14                 dec     ebx
seg000:0B16                 dec     ecx
seg000:0B18                 jmp     short loop
seg000:0B1A ; ---------------------------------------------------------------------------
seg000:0B1A
seg000:0B1A have_offset_value:
seg000:0B1A                 mov     ecx, edx
seg000:0B1D                 pop     edx
seg000:0B1F                 pop     ebx
seg000:0B21                 retn
seg000:0B21 GetDataRunOffset endp
seg000:0B21
seg000:0B22
seg000:0B22 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0B22
seg000:0B22 ; Description:
seg000:0B22 ;
seg000:0B22 ;   Converts the given unicode string to lowercase.
seg000:0B22 ;
seg000:0B22 ; Arguments:
seg000:0B22 ;
seg000:0B22 ;   DS:ESI - Pointer to the unicode string.
seg000:0B22 ;
seg000:0B22 ;   ECX - Number of characters in the string.
seg000:0B22 ;
seg000:0B22 ; Returns:
seg000:0B22 ;
seg000:0B22 ;   (No return value)
seg000:0B22 ;
seg000:0B22 ; Preserves/modifies:
seg000:0B22 ;
seg000:0B22 ;   Explicitly preserves ECX, ESI. No other 32-bit
seg000:0B22 ;   GP registers modified. No segment registers modified.
seg000:0B22 ;
seg000:0B22
seg000:0B22 UnicodeStringLwr proc near
seg000:0B22                 or      ecx, ecx
seg000:0B25                 jnz     @@1
seg000:0B29                 retn
seg000:0B2A ; ---------------------------------------------------------------------------
seg000:0B2A
seg000:0B2A @@1:
seg000:0B2A                 push    ecx
seg000:0B2C                 push    esi
seg000:0B2E
seg000:0B2E loop:
seg000:0B2E                 cmp     word ptr [esi], 'a'
seg000:0B32                 jl      @@2
seg000:0B36                 cmp     word ptr [esi], 'z'
seg000:0B3A                 jg      @@2
seg000:0B3E                 sub     word ptr [esi], 20h
seg000:0B42
seg000:0B42 @@2:
seg000:0B42                 add     esi, 2
seg000:0B46                 loop    loop
seg000:0B48                 pop     esi
seg000:0B4A                 pop     ecx
seg000:0B4C                 retn
seg000:0B4C UnicodeStringLwr endp
seg000:0B4C
seg000:0B4D
seg000:0B4D ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0B4D
seg000:0B4D ; Description:
seg000:0B4D ;
seg000:0B4D ;   Finds the specified file's index entry in the
seg000:0B4D ;   root directory index.
seg000:0B4D ;
seg000:0B4D ; Arguments:
seg000:0B4D ;
seg000:0B4D ;   DS:EAX - Pointer to the filename.
seg000:0B4D ;
seg000:0B4D ;   ECX - Length of the filename.
seg000:0B4D ;
seg000:0B4D ; Returns:
seg000:0B4D ;
seg000:0B4D ;   DS:EAX - Pointer to the file's index entry. If the
seg000:0B4D ;            file index entry was not found, EAX is zero.
seg000:0B4D ;
seg000:0B4D ; Preserves/modifies:
seg000:0B4D ;
seg000:0B4D ;   (No explicit preservations)
seg000:0B4D
seg000:0B4D FindFileInRootdIndex proc near
seg000:0B4D                 push    eax
seg000:0B4F                 push    ecx
seg000:0B51                 mov     edx, eax
seg000:0B54                 mov     eax, ds:pRootdIndexRootHdr
seg000:0B58                 lea     ebx, [eax+(size STD_ATTRIB_HDR)]
seg000:0B5D                 add     ax, [ebx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:0B61                 lea     eax, [eax+(size INDEX_ROOT_ATTRIB)]
seg000:0B66                 mov     ebx, edx
seg000:0B69                 call    FindFileIndexEntry
seg000:0B6C                 or      eax, eax
seg000:0B6F                 jz      not_found_in_index_root
seg000:0B73                 pop     ecx
seg000:0B75                 pop     ecx
seg000:0B77                 retn
seg000:0B78 ; ---------------------------------------------------------------------------
seg000:0B78
seg000:0B78 not_found_in_index_root:
seg000:0B78                 mov     eax, ds:pIndexAllocHdr
seg000:0B7C                 or      eax, eax
seg000:0B7F                 jnz     search_in_index_allocation
seg000:0B83                 pop     ecx
seg000:0B85                 pop     ecx
seg000:0B87                 xor     eax, eax
seg000:0B8A                 retn
seg000:0B8B ; ---------------------------------------------------------------------------
seg000:0B8B
seg000:0B8B search_in_index_allocation:
seg000:0B8B                 mov     edx, ds:pIndexAllocHdr
seg000:0B90                 lea     edx, [edx+(size STD_ATTRIB_HDR)]
seg000:0B95                 mov     eax, dword ptr [edx+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0B9A                 inc     eax
seg000:0B9C                 mov     ebx, ds:BytesPerCluster
seg000:0BA1                 mul     ebx
seg000:0BA4                 xor     edx, edx
seg000:0BA7                 div     ds:SizeOfIaEntry
seg000:0BAC                 push    eax
seg000:0BAE
seg000:0BAE search_next_index_buffer:
seg000:0BAE                 pop     eax
seg000:0BB0                 or      eax, eax
seg000:0BB3                 jz      not_found_in_index_allocation
seg000:0BB7                 dec     eax
seg000:0BB9                 push    eax
seg000:0BBB                 call    CheckIaEntryIsInUse
seg000:0BBE                 jb      short search_next_index_buffer
seg000:0BC0                 call    GetIndexAllocEntry
seg000:0BC3                 pop     edx
seg000:0BC5                 pop     ecx
seg000:0BC7                 pop     ebx
seg000:0BC9                 push    ebx
seg000:0BCB                 push    ecx
seg000:0BCD                 push    edx
seg000:0BCF                 mov     eax, ds:pIndexAllocEntry
seg000:0BD3                 lea     eax, [eax+(size NTFS_INDEX_RECORD)]
seg000:0BD8                 call    FindFileIndexEntry
seg000:0BDB                 or      eax, eax
seg000:0BDE                 jz      short search_next_index_buffer
seg000:0BE0                 pop     ecx
seg000:0BE2                 pop     ecx
seg000:0BE4                 pop     ecx
seg000:0BE6                 retn
seg000:0BE7 ; ---------------------------------------------------------------------------
seg000:0BE7
seg000:0BE7 not_found_in_index_allocation:
seg000:0BE7                 pop     ecx
seg000:0BE9                 pop     ecx
seg000:0BEB                 xor     eax, eax
seg000:0BEE                 retn
seg000:0BEE FindFileInRootdIndex endp
seg000:0BEE
seg000:0BEF
seg000:0BEF ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0BEF
seg000:0BEF ; Description:
seg000:0BEF ;
seg000:0BEF ;   Retrieves the specified directory attribute from
seg000:0BEF ;   the root directory file record.
seg000:0BEF ;
seg000:0BEF ; Arguments:
seg000:0BEF ;
seg000:0BEF ;   EAX - Directory attribute type.
seg000:0BEF ;
seg000:0BEF ;   DS:ECX - Memory buffer for the root directory's
seg000:0BEF ;            file record segment containing the specified
seg000:0BEF ;            directory attribute's header.
seg000:0BEF ;
seg000:0BEF ; Returns:
seg000:0BEF ;
seg000:0BEF ;   DS:EAX - Pointer to the attribute's standard
seg000:0BEF ;            attribute header. If the specified
seg000:0BEF ;            directory attribute was not found, EAX is
seg000:0BEF ;            zero.
seg000:0BEF ;
seg000:0BEF ; Preserves/modifies:
seg000:0BEF ;
seg000:0BEF ;   (No explicit preservations)
seg000:0BEF
seg000:0BEF GetRootdAttribHdr proc near
seg000:0BEF                 push    ecx
seg000:0BF1                 push    eax
seg000:0BF3                 mov     eax, FILE_ROOT_DIRECTORY
seg000:0BF9                 push    ds
seg000:0BFA                 pop     es
seg000:0BFB                 mov     edi, ecx
seg000:0BFE                 call    GetFileRecord
seg000:0C01                 mov     eax, ecx
seg000:0C04                 pop     ebx
seg000:0C06                 push    ebx
seg000:0C08                 movzx   ecx, ds:aI30_length
seg000:0C0E                 mov     edx, offset aI30 ; "$I30"
seg000:0C14                 call    FindAttribute
seg000:0C17                 pop     ebx
seg000:0C19                 pop     ecx
seg000:0C1B                 or      eax, eax
seg000:0C1E                 jnz     return
seg000:0C22                 mov     eax, ecx
seg000:0C25                 mov     ecx, ebx
seg000:0C28                 push    eax
seg000:0C2A                 push    ebx
seg000:0C2C                 call    GetFrsWithAttribType
seg000:0C2F                 pop     ebx
seg000:0C31                 pop     edi
seg000:0C33                 or      eax, eax
seg000:0C36                 jz      return
seg000:0C3A                 push    ds
seg000:0C3B                 pop     es
seg000:0C3C                 call    GetFileRecord
seg000:0C3F                 mov     eax, edi
seg000:0C42                 movzx   ecx, ds:aI30_length
seg000:0C48                 mov     edx, offset aI30 ; "$I30"
seg000:0C4E                 call    FindAttribute
seg000:0C51
seg000:0C51 return:
seg000:0C51                 retn
seg000:0C51 GetRootdAttribHdr endp
seg000:0C51
seg000:0C52
seg000:0C52 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0C52
seg000:0C52 ; Description:
seg000:0C52 ;
seg000:0C52 ;   Retrieves the file record number of the file record
seg000:0C52 ;   segment containing the specified attribute type.
seg000:0C52 ;
seg000:0C52 ; Arguments:
seg000:0C52 ;
seg000:0C52 ;   ECX - Attribute type.
seg000:0C52 ;
seg000:0C52 ;   DS:EAX - Pointer to the base file record segment.
seg000:0C52 ;
seg000:0C52 ; Returns:
seg000:0C52 ;
seg000:0C52 ;   EAX - File record number of the file record segment
seg000:0C52 ;         containing the specified attribute type.
seg000:0C52 ;
seg000:0C52 ; Preserves/modifies:
seg000:0C52 ;
seg000:0C52 ;   (No explicit preservations)
seg000:0C52
seg000:0C52 GetFrsWithAttribType proc near
seg000:0C52                 push    ecx
seg000:0C54                 mov     ebx, $ATTRIBUTE_LIST
seg000:0C5A                 mov     ecx, 0
seg000:0C60                 mov     edx, 0
seg000:0C66                 call    FindAttribute
seg000:0C69                 or      eax, eax
seg000:0C6C                 jz      no_record_extents_exist
seg000:0C70                 mov     ebx, eax
seg000:0C73                 push    ds
seg000:0C74                 pop     es
seg000:0C75                 mov     edi, ds:pAttribListData
seg000:0C7A                 call    GetAttributeData
seg000:0C7D                 push    ds
seg000:0C7E                 pop     es
seg000:0C7F                 mov     ebx, ds:pAttribListData
seg000:0C84                 pop     ecx
seg000:0C86
seg000:0C86 search_next_attribute:
seg000:0C86                 cmp     es:[bx+ATTRIB_LIST_ENTRY.Type], ecx
seg000:0C8A                 jz      found_attribute
seg000:0C8E                 cmp     es:[bxATTRIB_LIST_ENTRY.Type], -1
seg000:0C93                 jz      attribute_not_found
seg000:0C97                 cmp     es:[bx+ATTRIB_LIST_ENTRY.RecordLength], 0
seg000:0C9C                 jz      attribute_not_found
seg000:0CA0                 movzx   eax, es:[bx+ATTRIB_LIST_ENTRY.RecordLength]
seg000:0CA6                 add     bx, ax
seg000:0CA8                 mov     ax, bx
seg000:0CAA                 and     ax, 8000h
seg000:0CAD                 jz      short search_next_attribute
seg000:0CAF                 mov     ax, es
seg000:0CB1                 add     ax, 800h
seg000:0CB4                 mov     es, ax
seg000:0CB6                 assume es:nothing
seg000:0CB6                 and     bx, 7FFFh
seg000:0CBA                 jmp     short search_next_attribute
seg000:0CBC ; ---------------------------------------------------------------------------
seg000:0CBC
seg000:0CBC found_attribute:
seg000:0CBC                 mov     eax, dword ptr es:[bx+ATTRIB_LIST_ENTRY.BaseFileReference]
seg000:0CC1                 retn
seg000:0CC2 ; ---------------------------------------------------------------------------
seg000:0CC2
seg000:0CC2 no_record_extents_exist:
seg000:0CC2                 pop     ecx
seg000:0CC4
seg000:0CC4 attribute_not_found:
seg000:0CC4                 xor     eax, eax
seg000:0CC7                 retn
seg000:0CC7 GetFrsWithAttribType endp
seg000:0CC7
seg000:0CC8 ; ---------------------------------------------------------------------------
seg000:0CC8
seg000:0CC8 error_ntldr_missing:
seg000:0CC8                 mov     al, ds:ntldrIsMissingMsg
seg000:0CCB                 jmp     display_error_message
seg000:0CCE ; ---------------------------------------------------------------------------
seg000:0CCE
seg000:0CCE error_ntldr_compressed:
seg000:0CCE                 mov     al, ds:ntldrIsCompressedMsg
seg000:0CD1                 jmp     display_error_message
seg000:0CD1 ; ---------------------------------------------------------------------------
seg000:0CD4                 align 2000h
seg000:0CD4 seg000          ends
seg000:0CD4
seg000:0CD4
seg000:0CD4                 end

Various structure definitions and enumerations used in the disassembly

FFFFFFFF
FFFFFFFF ; enum ATTRIBUTE_TYPES
FFFFFFFF $ATTRIBUTE_LIST  = 20h
FFFFFFFF $DATA            = 80h
FFFFFFFF $INDEX_ROOT      = 90h
FFFFFFFF $INDEX_ALLOCATION  = 0A0h
FFFFFFFF $BITMAP          = 0B0h
FFFFFFFF
FFFFFFFF ; ---------------------------------------------------------------------------
FFFFFFFF
FFFFFFFF ; enum NTFS_FILES
FFFFFFFF FILE_ROOT_DIRECTORY  = 5
FFFFFFFF
00000000 NTFS_BPB_EBPB   struc ; (sizeof=0x51)
00000000 OemId           db 8 dup(?)             ; char
00000008 BytesPerSector  dw ?
0000000A SectorsPerCluster db ?
0000000B NoOfSectorsToRead dw ?
0000000D LsnToRead       dd ?
00000011 ExtDiskAccessAvl db ?
00000012 MediaDescriptor db ?
00000013                 db ? ; undefined
00000014                 db ? ; undefined
00000015 SectorsPerTrack dw ?
00000017 NumberOfHeads   dw ?
00000019 PartitionBase   dd ?
0000001D ChsLimit        dd ?
00000021 DiskNumber      db ?
00000022                 db ? ; undefined
00000023                 db ? ; undefined
00000024                 db ? ; undefined
00000025 TotalSectors    dq ?
0000002D LcnOfMftBfrs    dq ?
00000035 LcnOfMftMirrorBfrs dq ?
0000003D ClustersPerFrs  dd ?
00000041 ClustersPerIndexBlock dd ?
00000045 VolumeSerialNumber db 8 dup(?)
0000004D Checksum        dd ?
00000051 NTFS_BPB_EBPB   ends
00000051
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 NTFS_FILE_RECORD struc ; (sizeof=0x30)
00000000 Magic           dd ?
00000004 UpdateSequenceOffset dw ?
00000006 UpdateSequenceSize dw ?
00000008 LogFileSequenceNumber dq ?
00000010 SequenceNumber  dw ?
00000012 HardLinkCount   dw ?
00000014 FirstAttribOffset dw ?
00000016 Flags           dw ?
00000018 RealSize        dd ?
0000001C AllocatedSize   dd ?
00000020 BfrReference    dq ?
00000028 NextAttributeId dw ?
0000002A                 db ? ; undefined
0000002B                 db ? ; undefined
0000002C MftRecordNumber dd ?
00000030 NTFS_FILE_RECORD ends
00000030
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_LIST_ENTRY struc ; (sizeof=0x1A)
00000000 Type            dd ?
00000004 RecordLength    dw ?
00000006 NameLength      db ?
00000007 NameOffset      db ?
00000008 StartingVcn     dq ?
00000010 BaseFileReference dq ?
00000018 AttributeId     dw ?
0000001A ATTRIB_LIST_ENTRY ends
0000001A
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 STD_ATTRIB_HDR  struc ; (sizeof=0x10)
00000000 Type            dd ?
00000004 Length          dd ?
00000008 NonresidentFlag db ?
00000009 NameLength      db ?
0000000A NameOffset      dw ?
0000000C Flags           dw ?
0000000E AttributeId     dw ?
00000010 STD_ATTRIB_HDR  ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_HDR_RESIDENT struc ; (sizeof=0x7)
00000000 AttributeLength dd ?
00000004 AttributeOffset dw ?
00000006 IndexedFlag     db ?
00000007 ATTRIB_HDR_RESIDENT ends
00000007
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_HDR_NONRESIDENT struc ; (sizeof=0x30)
00000000 StartingVcn     dq ?
00000008 LastVcn         dq ?
00000010 DataRunsOffset  dw ?
00000012 CompressionUnitSize dw ?
00000014                 db ? ; undefined
00000015                 db ? ; undefined
00000016                 db ? ; undefined
00000017                 db ? ; undefined
00000018 AllocatedSize   dq ?
00000020 RealSize        dq ?
00000028 InitializedDataSize dq ?
00000030 ATTRIB_HDR_NONRESIDENT ends
00000030
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ROOT_ATTRIB struc ; (sizeof=0x10)
00000000 AttributeType   dd ?
00000004 CollationRule   dd ?
00000008 SizeOfIaEntry   dd ?
0000000C ClustersPerIndxRecd db ?
0000000D padding         db 3 dup(?)
00000010 INDEX_ROOT_ATTRIB ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 NTFS_INDEX_RECORD struc ; (sizeof=0x18)
00000000 Magic           dd ?
00000004 UpdateSequenceOffset dw ?
00000006 UpdateSequenceSize dw ?
00000008 LogFileSequenceNumber dq ?
00000010 VcnInIndexAlloc dq ?
00000018 NTFS_INDEX_RECORD ends
00000018
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_HDR       struc ; (sizeof=0x10)
00000000 FirstEntryOffset dd ?
00000004 TotalSize       dd ?
00000008 AllocatedSize   dd ?
0000000C Flags           db ?
0000000D padding         db 3 dup(?)
00000010 INDEX_HDR       ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ENTRY     struc ; (sizeof=0x10)
00000000 FileReference   dq ?
00000008 IndexEntryLength dw ?
0000000A StreamLength    dw ?
0000000C Flags           db ?
0000000D padding         db 3 dup(?)
00000010 INDEX_ENTRY     ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ENTRY_FILENAME struc ; (sizeof=0x43)
00000000 ParentFileReference dq ?
00000008 FileCreationTime dq ?
00000010 LastModificationTime dq ?
00000018 FileRecordLastModTime dq ?
00000020 LastAccessTime  dq ?
00000028 AllocatedFileSize dq ?
00000030 RealFileSize    dq ?
00000038 FileFlags       dq ?
00000040 FileNameLength  db ?
00000041 FileNameNamespace db ?
00000042 FileName        db ?
00000043 INDEX_ENTRY_FILENAME ends
00000043