Newer
Older
AMI-Aptio-BIOS-Reversed / AmiModulePkg / ACPI / FsRecovery / FsRecovery.c
@Ajax Dong Ajax Dong 2 days ago 126 KB Restructure the repo
#include "FsRecovery.h"

//
// FsRecovery - UEFI Module (Regenerated from IDA)
// Total functions: 77
//

// Function: ZeroMem @ 0x260 (0x20 bytes)
// Index: 1/77

void *__cdecl ZeroMem(void *buf, unsigned int count)
{
  memset(buf, 0, count); /*0x277*/
  return buf; /*0x27e*/
}


// Function: CopyMem @ 0x280 (0x3f bytes)
// Index: 2/77

char *__cdecl CopyMem(char *dst, char *src, unsigned int count)
{
  unsigned int count_1; // edx
  char *dst_1; // edi
  char *src_1; // esi

  count_1 = count; /*0x28a*/
  if ( src < dst && &src[count - 1] >= dst ) /*0x298*/
  {
    src_1 = &src[count - 1]; /*0x2ac*/
    dst_1 = &dst[count - 1]; /*0x2ae*/
  }
  else
  {
    count_1 = count & 3; /*0x29c*/
    qmemcpy(dst, src, 4 * (count >> 2)); /*0x2a5*/
    src_1 = &src[4 * (count >> 2)]; /*0x2a5*/
    dst_1 = &dst[4 * (count >> 2)]; /*0x2a5*/
  }
  qmemcpy(dst_1, src_1, count_1); /*0x2b5*/
  return dst; /*0x2bc*/
}


// Function: SetMem @ 0x2c0 (0x15 bytes)
// Index: 3/77

void *__cdecl SetMem(void *buf, unsigned int count, char value)
{
  memset(buf, value, count); /*0x2cd*/
  return buf; /*0x2d3*/
}


// Function: SetMem32 @ 0x2e0 (0x1f bytes)
// Index: 4/77

int __cdecl SetMem32(int a1, int a2, int a3, int a4)
{
  do /*0x2f9*/
  {
    *(_DWORD *)(a1 + 8 * a2 - 8) = a3; /*0x2f1*/
    *(_DWORD *)(a1 + 8 * a2-- - 4) = a4; /*0x2f5*/
  }
  while ( a2 ); /*0x2f9*/
  return a1; /*0x2fd*/
}


// Function: SetMem32_2 @ 0x300 (0x15 bytes)
// Index: 5/77

void *__cdecl SetMem32_2(void *buf, unsigned int count, int value)
{
  memset32(buf, value, count); /*0x30d*/
  return buf; /*0x313*/
}


// Function: _ModuleEntryPoint @ 0x320 (0x18 bytes)
// Index: 6/77

EFI_STATUS ModuleEntryPoint(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  gSystemTable = (int)SystemTable; /*0x32a*/
  return (*(int (__cdecl **)(EFI_SYSTEM_TABLE *, void *))(LODWORD(SystemTable->Hdr.Signature) + 24))( /*0x337*/
           SystemTable,
           &unk_4B98);
}


// Function: MatchWildcard @ 0x338 (0xe1 bytes)
// Index: 7/77

bool __fastcall MatchWildcard(char *Pattern, char *StrToMatch, int CaseSensitive, int MaxLen)
{
  char *Pattern_1; // ebx
  int StrLenResult; // edx
  char PatChar; // dl
  char PatChar_2; // al
  char PatChar_1; // cl

  Pattern_1 = Pattern; /*0x341*/
  StrLen(Pattern); /*0x343*/
  if ( StrLen(StrToMatch) ) /*0x34c*/
  {
    while ( 1 ) /*0x35c*/
    {
      if ( !MaxLen ) /*0x35e*/
        return !StrLenResult || *Pattern_1 == 44; /*0x35e*/
      PatChar = *Pattern_1++; /*0x364*/
      switch ( PatChar ) /*0x370*/
      {
        case 0: /*0x370*/
          return 1; /*0x370*/
        case 42: /*0x370*/
          while ( *StrToMatch ) /*0x3ea*/
          {
            if ( MatchWildcard(Pattern_1, StrToMatch, CaseSensitive, MaxLen) ) /*0x3da*/
              return 1; /*0x3e3*/
            ++StrToMatch; /*0x3e5*/
            --MaxLen; /*0x3e6*/
          }
          goto LABEL_23; /*0x3ea*/
        case 44: /*0x370*/
          return 1; /*0x37f*/
      }
      if ( PatChar == 46 ) /*0x389*/
        break; /*0x389*/
      if ( PatChar != 63 ) /*0x38e*/
        goto LABEL_11; /*0x38e*/
      if ( !*StrToMatch ) /*0x390*/
        return 0; /*0x392*/
LABEL_16:
      ++StrToMatch; /*0x3c0*/
      --MaxLen; /*0x3c1*/
LABEL_23:
      StrLen(Pattern_1); /*0x3ec*/
      if ( !StrLen(StrToMatch) ) /*0x3f7*/
        return !StrLenResult || *Pattern_1 == 44; /*0x3fe*/
    }
    if ( (_BYTE)CaseSensitive == 1 ) /*0x39c*/
    {
      while ( *StrToMatch == 32 ) /*0x3ce*/
      {
        ++StrToMatch; /*0x3c8*/
        --MaxLen; /*0x3c9*/
      }
      goto LABEL_23; /*0x3ce*/
    }
LABEL_11:
    PatChar_2 = *StrToMatch; /*0x39e*/
    if ( (unsigned __int8)(*StrToMatch - 97) <= 0x19u ) /*0x3a9*/
      PatChar_2 -= 32; /*0x3ab*/
    PatChar_1 = PatChar; /*0x3ae*/
    if ( (unsigned __int8)(PatChar - 97) <= 0x19u ) /*0x3b7*/
      PatChar_1 = PatChar - 32; /*0x3b9*/
    if ( PatChar_2 != PatChar_1 ) /*0x3be*/
      return 0; /*0x396*/
    goto LABEL_16; /*0x3be*/
  }
  return !StrLenResult || *Pattern_1 == 44; /*0x40f*/
}


// Function: MatchNameWildcard @ 0x419 (0x54 bytes)
// Index: 8/77

int __fastcall MatchNameWildcard(char *DirEntry, int CaseSensitive, int MaxLen, char *Pattern)
{
  if ( !*DirEntry || !MaxLen ) /*0x430*/
    return -2147483646; /*0x424*/
  while ( 1 ) /*0x437*/
  {
    if ( *Pattern == 44 ) /*0x43a*/
      ++Pattern; /*0x43c*/
    if ( MatchWildcard(Pattern, DirEntry, CaseSensitive, MaxLen) ) /*0x446*/
      break; /*0x44f*/
    while ( *Pattern != 44 ) /*0x460*/
    {
      if ( !*Pattern ) /*0x459*/
        return -2147483646; /*0x466*/
      ++Pattern; /*0x45b*/
    }
  }
  return 0; /*0x454*/
}


// Function: FormatShortName @ 0x46d (0xed bytes)
// Index: 9/77

void __fastcall FormatShortName(char *SrcName, int OutputBuf_1)
{
  unsigned int i; // esi
  unsigned int NameLen; // edx
  int DestOffset; // esi
  char SrcByte; // al
  unsigned int ShortNameIdx; // esi
  int BufOffset; // edx
  char CurChar; // cl
  int BufIdx; // eax
  unsigned int ShortNameIdx_1; // edi
  char *CharIdx; // ecx
  char ExtChar; // al
  int OutputBuf; // [esp+10h] [ebp-14h]
  _BYTE v14[16]; // [esp+14h] [ebp-10h] BYREF

  OutputBuf = OutputBuf_1; /*0x474*/
  if ( byte_4BE9 ) /*0x480*/
  {
    for ( i = 0; i < 0xD; ++i ) /*0x482*/
    {
      v14[i] = SrcName[2 * i]; /*0x487*/
      if ( !*(_WORD *)&SrcName[2 * i] ) /*0x48b*/
        break; /*0x48f*/
    }
  }
  else
  {
    NameLen = 0; /*0x49d*/
    DestOffset = v14 - SrcName; /*0x49f*/
    do /*0x4af*/
    {
      SrcByte = *SrcName; /*0x4a1*/
      SrcName[DestOffset] = *SrcName; /*0x4a3*/
      if ( !SrcByte ) /*0x4a8*/
        break; /*0x4a8*/
      ++NameLen; /*0x4aa*/
      ++SrcName; /*0x4ab*/
    }
    while ( NameLen < 0xD ); /*0x4af*/
    OutputBuf_1 = OutputBuf; /*0x4b1*/
  }
  ShortNameIdx = 0; /*0x4ba*/
  if ( v14[0] ) /*0x4bc*/
  {
    BufOffset = OutputBuf_1 - (_DWORD)v14; /*0x4c2*/
    do /*0x4e2*/
    {
      CurChar = v14[ShortNameIdx]; /*0x4c4*/
      if ( CurChar == 46 ) /*0x4cb*/
        break; /*0x4cb*/
      if ( (unsigned __int8)(CurChar - 97) <= 0x19u ) /*0x4d5*/
        CurChar -= 32; /*0x4d7*/
      BufIdx = BufOffset + ShortNameIdx++; /*0x4da*/
      v14[BufIdx] = CurChar; /*0x4de*/
    }
    while ( v14[ShortNameIdx] ); /*0x4e2*/
  }
  ShortNameIdx_1 = ShortNameIdx; /*0x4ec*/
  if ( ShortNameIdx < 8 ) /*0x4f0*/
  {
    ReservedFunc1(); /*0x4fe*/
    ShortNameIdx = 8; /*0x506*/
  }
  if ( v14[ShortNameIdx_1] == 46 ) /*0x511*/
  {
    for ( CharIdx = &v14[ShortNameIdx_1 + 1]; *CharIdx; ++CharIdx ) /*0x518*/
    {
      ExtChar = *CharIdx; /*0x526*/
      if ( (unsigned __int8)(*CharIdx - 97) <= 0x19u ) /*0x529*/
        ExtChar -= 32; /*0x52b*/
      *(_BYTE *)(ShortNameIdx + OutputBuf) = ExtChar; /*0x52e*/
      ++ShortNameIdx; /*0x531*/
    }
  }
  if ( ShortNameIdx < 0xB ) /*0x53a*/
  {
    ReservedFunc1(); /*0x545*/
    ShortNameIdx = 11; /*0x54d*/
  }
  *(_BYTE *)(ShortNameIdx + OutputBuf) = 0; /*0x550*/
}


// Function: IsLongFileName @ 0x55a (0x87 bytes)
// Index: 10/77

bool __fastcall IsLongFileName(_WORD *FileName, int Param2)
{
  unsigned __int8 NameLen; // al
  unsigned __int8 NameLen_1; // dl
  unsigned __int8 NameLen_3; // cl
  int WideChar; // eax
  unsigned __int8 NameLen_2; // al

  if ( *(_BYTE *)(BootSector + 12) != 2 ) /*0x567*/
    return 0; /*0x56b*/
  if ( IsUnicode ) /*0x574*/
  {
    NameLen = StrLen_Unicode(FileName); /*0x576*/
    NameLen_1 = NameLen; /*0x57b*/
    if ( NameLen > 0xCu ) /*0x580*/
      return 1; /*0x584*/
    NameLen_3 = 0; /*0x586*/
    if ( NameLen ) /*0x58a*/
    {
      while ( 1 ) /*0x594*/
      {
        WideChar = (unsigned __int16)FileName[NameLen_3]; /*0x594*/
        if ( (unsigned __int16)WideChar > 0xFFu ) /*0x59b*/
          return 1; /*0x59b*/
        if ( WideChar != 46 && ++NameLen_3 < NameLen_1 ) /*0x5a6*/
          continue; /*0x5a6*/
        goto LABEL_10; /*0x5a6*/
      }
    }
  }
  else
  {
    NameLen_2 = StrLen(FileName); /*0x5be*/
    NameLen_1 = NameLen_2; /*0x5c3*/
    if ( NameLen_2 > 0xCu ) /*0x5c8*/
      return 1; /*0x5c8*/
    NameLen_3 = 0; /*0x5ca*/
    if ( NameLen_2 ) /*0x5ce*/
    {
      do /*0x5dd*/
      {
        if ( *((_BYTE *)FileName + NameLen_3) == 46 ) /*0x5d7*/
          break; /*0x5d7*/
        ++NameLen_3; /*0x5d9*/
      }
      while ( NameLen_3 < NameLen_2 ); /*0x5dd*/
LABEL_10:
      if ( NameLen_3 > 8u ) /*0x5ab*/
        return 1; /*0x5ab*/
    }
  }
  return NameLen_1 - NameLen_3 > 4; /*0x5bb*/
}


// Function: ExtractDirEntryName @ 0x5e1 (0xc8 bytes)
// Index: 11/77

char __fastcall ExtractDirEntryName(_BYTE *LfnEntryPtr, int a2)
{
  unsigned int EntryCount; // ebp
  int OutIdx; // esi
  __int16 *CurEntryPtr; // ecx
  char IsUnicode; // ah
  __int16 *v6; // edi
  int NamePart1Len; // ebx
  __int16 v8; // ax
  __int16 *CurEntryPtr_1; // edi
  int NamePart2Len; // ebx
  __int16 v11; // ax
  __int16 *v12; // edi
  int ExtPartLen; // ebx
  __int16 v14; // ax
  char AsciiByte; // al
  char *CurEntryPtr_2; // edi
  int n6; // ebx
  char AsciiChar; // al
  _BYTE *AsciiExtPtr; // edi
  int n2; // ebx
  unsigned int EntryCount_1; // [esp+10h] [ebp-4h]

  EntryCount = 0; /*0x5ee*/
  EntryCount_1 = *LfnEntryPtr & 0x1F; /*0x5f0*/
  OutIdx = 0; /*0x5f8*/
  CurEntryPtr = (__int16 *)&LfnEntryPtr[32 * EntryCount_1 - 18]; /*0x5fa*/
  IsUnicode = ::IsUnicode; /*0x5fc*/
  do /*0x68d*/
  {
    v6 = (__int16 *)((char *)CurEntryPtr - 13); /*0x603*/
    NamePart1Len = 5; /*0x608*/
    if ( IsUnicode ) /*0x60b*/
    {
      do /*0x61b*/
      {
        v8 = *v6++; /*0x60d*/
        *(_WORD *)(a2 + 2 * OutIdx++) = v8; /*0x613*/
        --NamePart1Len; /*0x618*/
      }
      while ( NamePart1Len ); /*0x61b*/
      CurEntryPtr_1 = CurEntryPtr; /*0x61f*/
      NamePart2Len = 6; /*0x621*/
      do /*0x630*/
      {
        v11 = *CurEntryPtr_1++; /*0x622*/
        *(_WORD *)(a2 + 2 * OutIdx++) = v11; /*0x628*/
        --NamePart2Len; /*0x62d*/
      }
      while ( NamePart2Len ); /*0x630*/
      v12 = CurEntryPtr + 7; /*0x634*/
      ExtPartLen = 2; /*0x637*/
      do /*0x646*/
      {
        v14 = *v12++; /*0x638*/
        *(_WORD *)(a2 + 2 * OutIdx++) = v14; /*0x63e*/
        --ExtPartLen; /*0x643*/
      }
      while ( ExtPartLen ); /*0x646*/
      IsUnicode = ::IsUnicode; /*0x648*/
    }
    else
    {
      do /*0x65c*/
      {
        AsciiByte = *(_BYTE *)v6++; /*0x650*/
        *(_BYTE *)(OutIdx + a2) = AsciiByte; /*0x655*/
        ++OutIdx; /*0x658*/
        --NamePart1Len; /*0x659*/
      }
      while ( NamePart1Len ); /*0x65c*/
      CurEntryPtr_2 = (char *)CurEntryPtr; /*0x660*/
      n6 = 6; /*0x662*/
      do /*0x66f*/
      {
        AsciiChar = *CurEntryPtr_2; /*0x663*/
        CurEntryPtr_2 += 2; /*0x665*/
        *(_BYTE *)(OutIdx + a2) = AsciiChar; /*0x668*/
        ++OutIdx; /*0x66b*/
        --n6; /*0x66c*/
      }
      while ( n6 ); /*0x66f*/
      AsciiExtPtr = CurEntryPtr + 7; /*0x673*/
      n2 = 2; /*0x676*/
      do /*0x683*/
      {
        LOBYTE(v14) = *AsciiExtPtr; /*0x677*/
        AsciiExtPtr += 2; /*0x679*/
        *(_BYTE *)(OutIdx + a2) = v14; /*0x67c*/
        ++OutIdx; /*0x67f*/
        --n2; /*0x680*/
      }
      while ( n2 ); /*0x683*/
    }
    CurEntryPtr -= 16; /*0x685*/
    ++EntryCount; /*0x688*/
  }
  while ( EntryCount < EntryCount_1 ); /*0x68d*/
  if ( IsUnicode ) /*0x695*/
  {
    *(_WORD *)(a2 + 2 * OutIdx) = 0; /*0x699*/
    LOBYTE(v14) = 0; /*0x697*/
  }
  else
  {
    *(_BYTE *)(OutIdx + a2) = 0; /*0x69f*/
  }
  return v14; /*0x6a3*/
}


// Function: StrCmpUnicodeOrAscii @ 0x6a9 (0xd9 bytes)
// Index: 12/77

char __fastcall StrCmpUnicodeOrAscii(_WORD *Str1, _WORD *Str2)
{
  unsigned int Len1; // esi
  unsigned __int8 CharIdx; // bl
  int Idx1; // esi
  __int16 Ch1; // cx
  __int16 Ch2; // dx
  __int16 Ch1_1; // ax
  int Len2; // eax
  int Len2_1; // edx
  unsigned __int8 CharIdxA; // bl
  unsigned int CharIdxA_1; // esi
  int IdxA; // ecx
  char Ch1A; // dl
  char Ch1A_2; // cl
  char Ch1A_1; // al

  if ( IsUnicode ) /*0x6b8*/
  {
    Len1 = StrLen_Unicode(Str1); /*0x6c1*/
    if ( Len1 != StrLen_Unicode(Str2) ) /*0x6ca*/
      return 0; /*0x6ce*/
    CharIdx = 0; /*0x6d5*/
    if ( StrLen_Unicode(Str1) ) /*0x6d7*/
    {
      Idx1 = 0; /*0x6e6*/
      while ( 1 ) /*0x6e9*/
      {
        Ch1 = Str1[Idx1]; /*0x6e9*/
        if ( (unsigned __int16)(Ch1 - 97) <= 0x19u ) /*0x6f3*/
          Ch1 -= 32; /*0x6f5*/
        Ch2 = Str2[Idx1]; /*0x6f8*/
        Ch1_1 = Ch2 - 32; /*0x706*/
        if ( (unsigned __int16)(Ch2 - 97) > 0x19u ) /*0x709*/
          Ch1_1 = Str2[Idx1]; /*0x70b*/
        if ( Ch1 != Ch1_1 ) /*0x710*/
          break; /*0x710*/
        Idx1 = ++CharIdx; /*0x716*/
        if ( CharIdx >= StrLen_Unicode(Str1) ) /*0x723*/
          return 1; /*0x723*/
      }
      return 0; /*0x710*/
    }
  }
  else
  {
    StrLen(Str1); /*0x727*/
    Len2 = StrLen(Str2); /*0x730*/
    if ( Len2_1 != Len2 ) /*0x737*/
      return 0; /*0x737*/
    CharIdxA = 0; /*0x73b*/
    CharIdxA_1 = StrLen(Str1); /*0x742*/
    if ( CharIdxA_1 ) /*0x746*/
    {
      IdxA = 0; /*0x748*/
      while ( 1 ) /*0x750*/
      {
        Ch1A = *((_BYTE *)Str1 + IdxA); /*0x750*/
        if ( (unsigned __int8)(Ch1A - 97) <= 0x19u ) /*0x755*/
          Ch1A -= 32; /*0x757*/
        Ch1A_2 = *((_BYTE *)Str2 + IdxA); /*0x75a*/
        Ch1A_1 = Ch1A_2; /*0x762*/
        if ( (unsigned __int8)(Ch1A_2 - 97) <= 0x19u ) /*0x765*/
          Ch1A_1 = Ch1A_2 - 32; /*0x767*/
        if ( Ch1A != Ch1A_1 ) /*0x76c*/
          break; /*0x76c*/
        IdxA = ++CharIdxA; /*0x774*/
        if ( CharIdxA >= CharIdxA_1 ) /*0x779*/
          return 1; /*0x779*/
      }
      return 0; /*0x76c*/
    }
  }
  return 1; /*0x77d*/
}


// Function: ReadBlocks @ 0x782 (0x114 bytes)
// Index: 13/77

int __fastcall ReadBlocks(int a1, int a2, __int64 a3, unsigned int BufSize, unsigned int DstBuffer)
{
  unsigned __int64 AbsBlockAddr; // kr00_8
  unsigned __int64 AlignedBlockAddr; // rax
  int ByteOffset; // esi
  int BlockAddrHi; // ebp
  int AlignedBlockAddr_1; // ebx
  int PageCount; // edx
  int result; // eax
  int CacheBufAddr; // ecx
  int IoStatus; // edi
  unsigned int ReadSize; // [esp+14h] [ebp-Ch]
  int CacheBufAddr_1; // [esp+18h] [ebp-8h] BYREF
  int AllocSize; // [esp+24h] [ebp+4h]

  AbsBlockAddr = *(_QWORD *)(a2 + 21) + a3; /*0x79a*/
  if ( *(_DWORD *)a2 == 4096 ) /*0x7a5*/
  {
    AlignedBlockAddr = RShiftU64(AbsBlockAddr); /*0x7a9*/
    ByteOffset = AbsBlockAddr & 0xFFF; /*0x7ae*/
  }
  else if ( *(_DWORD *)a2 == 2048 ) /*0x7bc*/
  {
    AlignedBlockAddr = RShiftU64(AbsBlockAddr); /*0x7c0*/
    ByteOffset = AbsBlockAddr & 0x7FF; /*0x7c5*/
  }
  else
  {
    AlignedBlockAddr = RShiftU64(AbsBlockAddr); /*0x7cf*/
    ByteOffset = AbsBlockAddr & 0x1FF; /*0x7d4*/
  }
  BlockAddrHi = HIDWORD(AlignedBlockAddr); /*0x7da*/
  AlignedBlockAddr_1 = AlignedBlockAddr; /*0x7dc*/
  ReadSize = *(_DWORD *)a2 * ((BufSize - 1 + *(_DWORD *)a2 + ByteOffset) / *(_DWORD *)a2); /*0x7f5*/
  PageCount = (ReadSize >> 12) /*0x80a*/
            + (((*(_WORD *)a2 * (unsigned __int16)((BufSize - 1 + *(_DWORD *)a2 + ByteOffset) / *(_DWORD *)a2)) & 0xFFF) != 0);
  AllocSize = PageCount << 12; /*0x811*/
  if ( ::AllocSize >= (unsigned int)(PageCount << 12) ) /*0x81b*/
  {
    CacheBufAddr = ::CacheBufAddr; /*0x84f*/
  }
  else
  {
    result = (*(int (__cdecl **)(int, int, int, int *))(*(_DWORD *)a1 + 72))(a1, 4, PageCount, &CacheBufAddr_1); /*0x830*/
    if ( result < 0 ) /*0x838*/
      return result; /*0x838*/
    CacheBufAddr = CacheBufAddr_1; /*0x83a*/
    ::CacheBufAddr = CacheBufAddr_1; /*0x842*/
    ::AllocSize = AllocSize; /*0x848*/
  }
  IoStatus = (*(int (__cdecl **)(int, _DWORD, _DWORD, int, int, unsigned int, int))(*(_DWORD *)(a2 + 4) + 8))( /*0x86a*/
               a1,
               *(_DWORD *)(a2 + 4),
               *(_DWORD *)(a2 + 8),
               AlignedBlockAddr_1,
               BlockAddrHi,
               ReadSize,
               CacheBufAddr);
  if ( IoStatus >= 0 ) /*0x871*/
    CopyMemEx(DstBuffer, (char *)(ByteOffset + ::CacheBufAddr), BufSize); /*0x884*/
  return IoStatus; /*0x88e*/
}


// Function: IsValidMbrPartition @ 0x896 (0x42 bytes)
// Index: 14/77

int __thiscall IsValidMbrPartition(char *this)
{
  int result; // eax
  unsigned __int8 n0x80; // dl
  char v3; // cl

  result = 0; /*0x89b*/
  if ( *(_WORD *)(this + 11) <= 0x1000u ) /*0x8a1*/
  {
    n0x80 = *(this + 13); /*0x8a3*/
    if ( n0x80 ) /*0x8a8*/
    {
      if ( n0x80 <= 0x80u ) /*0x8ad*/
      {
        if ( *((_WORD *)this + 7) ) /*0x8af*/
        {
          if ( *(this + 16) ) /*0x8b5*/
          {
            if ( *((_WORD *)this + 255) == 0xAA55 ) /*0x8c6*/
            {
              v3 = *this; /*0x8c8*/
              if ( v3 == -21 || v3 == -23 ) /*0x8d2*/
                return 1; /*0x8d6*/
            }
          }
        }
      }
    }
  }
  return result; /*0x8d7*/
}


// Function: ReadClusterChain @ 0x8d8 (0x51 bytes)
// Index: 15/77

int __fastcall ReadClusterChain(int ClusterNum)
{
  int ClusterNum_1; // esi
  int CacheOffset; // edx
  int result; // eax

  ClusterNum_1 = ClusterNum; /*0x8d9*/
  CacheOffset = *(_DWORD *)(i_0[0] + 12); /*0x8e1*/
  if ( (unsigned int)(CacheOffset + ClusterNum) >= *(_DWORD *)(i_0[0] + 16) ) /*0x8ea*/
    ClusterNum_1 = *(_DWORD *)(i_0[0] + 16) - CacheOffset; /*0x8ef*/
  result = ReadBlocks( /*0x911*/
             SystemTable,
             BootSector,
             *(_QWORD *)(BootSector + 29) + (unsigned int)(4 * ClusterNum_1),
             *(_DWORD *)(i_0[0] + 4),
             *(_DWORD *)i_0[0]);
  if ( result >= 0 ) /*0x91b*/
  {
    *(_DWORD *)(i_0[0] + 8) = ClusterNum_1; /*0x922*/
    return 0; /*0x925*/
  }
  return result; /*0x927*/
}


// Function: InitCache @ 0x929 (0xdd bytes)
// Index: 16/77

int __fastcall InitCache(int BlockIoHandle, int BootSector, unsigned int n0x20000)
{
  int CacheStructPtr; // eax
  int result; // eax
  int CacheBlockSize; // ecx
  int v8; // [esp+10h] [ebp-8h] BYREF

  CacheStructPtr = i_0[0]; /*0x92b*/
  if ( !i_0[0] ) /*0x93a*/
  {
    result = (*(int (__cdecl **)(int, int, int *))(*(_DWORD *)BlockIoHandle + 76))(BlockIoHandle, 20, i_0); /*0x946*/
    if ( result < 0 ) /*0x94e*/
      return result; /*0x94e*/
    result = (*(int (__cdecl **)(int, int, int, int *))(*(_DWORD *)BlockIoHandle + 72))(BlockIoHandle, 4, 32, &v8); /*0x960*/
    if ( result < 0 ) /*0x968*/
    {
      i_0[0] = 0; /*0x96a*/
      return result; /*0x971*/
    }
    *(_DWORD *)i_0[0] = v8; /*0x97f*/
    CacheStructPtr = i_0[0]; /*0x981*/
  }
  CacheBlockSize = n0x20000; /*0x98f*/
  if ( n0x20000 >= 0x20000 ) /*0x993*/
    CacheBlockSize = 0x4000; /*0x995*/
  *(_DWORD *)(CacheStructPtr + 4) = CacheBlockSize; /*0x99a*/
  ZeroMemEx(i_0[0], *(char **)i_0[0], *(_DWORD *)(i_0[0] + 4), 0); /*0x9a9*/
  result = ReadBlocks( /*0x9c5*/
             BlockIoHandle,
             BootSector,
             *(_QWORD *)(BootSector + 29),
             *(_DWORD *)(i_0[0] + 4),
             *(_DWORD *)i_0[0]);
  if ( result >= 0 )
  {
    *(_DWORD *)(i_0[0] + 8) = 0; /*0x9d6*/
    *(_DWORD *)(i_0[0] + 12) = n0x20000 < 0x20000 ? -1 : 4096;
    *(_DWORD *)(i_0[0] + 16) = n0x20000 >> 2; /*0x9fa*/
    return 0; /*0x9fd*/
  }
  return result; /*0x9ff*/
}


// Function: WalkClusterChain @ 0xa06 (0x15d bytes)
// Index: 17/77

int __fastcall WalkClusterChain(char FatType, unsigned int ClusterNum, char **p_i, char SequentialOnly)
{
  unsigned int ClusterNum_1; // ebx
  int ClusterCount; // esi
  unsigned int ClusterNum_2; // ecx
  _DWORD *FatTablePtr; // edx
  _DWORD *i; // edx
  unsigned int FatEntryVal; // ecx

  ClusterNum_1 = ClusterNum; /*0xa0c*/
  ClusterCount = 0; /*0xa0e*/
  switch ( FatType ) /*0xa14*/
  {
    case 1: /*0xa14*/
      ClusterCount = 1; /*0xa1b*/
      ClusterNum_2 = *(unsigned __int16 *)(*(_DWORD *)i_0[0] + 2 * ClusterNum); /*0xa1e*/
      if ( ClusterNum_2 <= 0xFFF7 ) /*0xa28*/
      {
        while ( ClusterNum_2 == ClusterNum_1 + 1 || !SequentialOnly ) /*0xa37*/
        {
          ClusterNum_1 = ClusterNum_2; /*0xa39*/
          ++ClusterCount; /*0xa3b*/
          ClusterNum_2 = *(unsigned __int16 *)(*(_DWORD *)i_0[0] + 2 * ClusterNum_2); /*0xa3c*/
          if ( ClusterNum_2 > 0xFFF7 ) /*0xa46*/
            goto LABEL_6; /*0xa46*/
        }
LABEL_17:
        *p_i = (char *)ClusterNum_2; /*0xaa9*/
        return ClusterCount; /*0xaaf*/
      }
LABEL_6:
      *p_i = 0; /*0xa48*/
      return ClusterCount; /*0xa4e*/
    case 2: /*0xa14*/
      for ( FatTablePtr = (_DWORD *)i_0[0]; /*0xa58*/
            ;
            ClusterNum_1 = *(_DWORD *)(*FatTablePtr + 4 * (ClusterNum_1 - FatTablePtr[2])) & 0xFFFFFFF )
      {
        ++ClusterCount; /*0xa5e*/
        if ( ClusterNum_1 < FatTablePtr[2] || ClusterNum_1 >= FatTablePtr[2] + FatTablePtr[3] ) /*0xa6c*/
        {
          if ( ReadClusterChain(ClusterNum_1) < 0 ) /*0xa77*/
            return 0; /*0xa77*/
          FatTablePtr = (_DWORD *)i_0[0]; /*0xa79*/
        }
        ClusterNum_2 = *(_DWORD *)(*FatTablePtr + 4 * (ClusterNum_1 - FatTablePtr[2])) & 0xFFFFFFF; /*0xa89*/
        if ( ClusterNum_2 > 0xFFFFFF7 ) /*0xa95*/
          break; /*0xa95*/
        if ( ClusterNum_2 != ClusterNum_1 + 1 && SequentialOnly ) /*0xaa3*/
          goto LABEL_17; /*0xaa3*/
      }
      goto LABEL_6; /*0xa95*/
    case 5: /*0xa14*/
      for ( i = (_DWORD *)i_0[0]; ; ClusterNum_1 = *(_DWORD *)(*i + 4 * (ClusterNum_1 - i[2])) ) /*0xac0*/
      {
        ++ClusterCount; /*0xac6*/
        if ( ClusterNum_1 < i[2] || ClusterNum_1 >= i[2] + i[3] ) /*0xad4*/
        {
          if ( ReadClusterChain(ClusterNum_1) < 0 ) /*0xadf*/
            return 0; /*0xab6*/
          i = (_DWORD *)i_0[0]; /*0xae1*/
        }
        ClusterNum_2 = *(_DWORD *)(*i + 4 * (ClusterNum_1 - i[2])); /*0xaee*/
        if ( ClusterNum_2 > 0xFFFFFFF7 || !ClusterNum_2 ) /*0xafc*/
          goto LABEL_6; /*0xafc*/
        if ( ClusterNum_2 != ClusterNum_1 + 1 && SequentialOnly ) /*0xb0e*/
          goto LABEL_17; /*0xb0e*/
      }
      break;
  }
  while ( 1 )
  {
    ++ClusterCount; /*0xb21*/
    FatEntryVal = *(unsigned __int16 *)(*(_DWORD *)i_0[0] + (ClusterNum_1 >> 1) + ClusterNum_1); /*0xb26*/
    ClusterNum_2 = (ClusterNum_1 & 1) != 0 ? FatEntryVal >> 4 : FatEntryVal & 0xFFF;
    if ( ClusterNum_2 > 0xFF7 ) /*0xb40*/
      break; /*0xb40*/
    if ( ClusterNum_2 != ClusterNum_1 + 1 && SequentialOnly ) /*0xb4b*/
      goto LABEL_17; /*0xb4b*/
    ClusterNum_1 = ClusterNum_2; /*0xb51*/
  }
  *p_i = 0; /*0xb59*/
  return ClusterCount; /*0xb5d*/
}


// Function: ReadFileData @ 0xb63 (0x8a bytes)
// Index: 18/77

int __fastcall ReadFileData(
        int BlockIoHandle,
        int BootSector,
        char *StartCluster,
        unsigned int BytesRemaining,
        unsigned int DstBuffer)
{
  char *StartCluster_1; // ebx
  int BootSector_1; // eax
  unsigned int DstBuffer_1; // ebp
  unsigned int i; // esi
  unsigned int i_1; // edi
  int ClusterChainLen; // eax
  __int64 BlockOffset; // rax
  int result; // eax

  StartCluster_1 = StartCluster; /*0xb66*/
  BootSector_1 = BootSector; /*0xb6a*/
  DstBuffer_1 = DstBuffer; /*0xb6d*/
  for ( i = BytesRemaining; ; i -= i_1 ) /*0xb72*/
  {
    i_1 = i; /*0xb8b*/
    ClusterChainLen = WalkClusterChain(*(_BYTE *)(BootSector_1 + 12), (unsigned int)StartCluster_1, &StartCluster, 1); /*0xb8d*/
    if ( i > ClusterChainLen * *(_DWORD *)(BootSector + 53) ) /*0xba2*/
      i_1 = ClusterChainLen * *(_DWORD *)(BootSector + 53); /*0xba4*/
    BlockOffset = MultU64x32((unsigned int)(StartCluster_1 - 2)); /*0xbae*/
    result = ReadBlocks(BlockIoHandle, BootSector, *(_QWORD *)(BootSector + 45) + BlockOffset, i_1, DstBuffer_1); /*0xbc8*/
    if ( result < 0 ) /*0xbd2*/
      break; /*0xbd2*/
    StartCluster_1 = StartCluster; /*0xbd4*/
    if ( !StartCluster ) /*0xbda*/
      break; /*0xbda*/
    BootSector_1 = BootSector; /*0xbdc*/
    DstBuffer_1 += i_1; /*0xbe0*/
  }
  return result; /*0xbe6*/
}


// Function: ParseNtfsBootSector @ 0xbed (0x1bf bytes)
// Index: 19/77

int __fastcall ParseNtfsBootSector(char *Buffer, int BootSector, unsigned int NtfsVbr)
{
  unsigned int NtfsVbr_1; // edi
  unsigned int NtfsVbr_2; // ecx
  int BytesPerSectorVal; // ebp
  int TotalSectorsVal; // eax
  int MftZoneSectors; // eax
  int MftStartLba; // esi
  unsigned int MftByteSize; // ebp
  __int64 MftOffset; // rax
  unsigned int DataOffset; // ecx
  bool v13; // cf
  char ClusterFactorVal; // al
  char *CacheBufPtr; // esi
  int Status; // eax
  int i; // eax
  char *AllocBufSize; // ecx
  int TotalSectorsVal_1; // [esp+10h] [ebp-10h]
  unsigned int ClustersPerMftRec; // [esp+10h] [ebp-10h]
  int CacheByteSize; // [esp+14h] [ebp-Ch]
  char *AllocBufPtr; // [esp+18h] [ebp-8h] BYREF

  NtfsVbr_1 = NtfsVbr; /*0xbf4*/
  AllocBufPtr = Buffer; /*0xbfa*/
  if ( *(_WORD *)(NtfsVbr + 22) ) /*0xbfe*/
    NtfsVbr_2 = *(unsigned __int16 *)(NtfsVbr + 22); /*0xc07*/
  else
    NtfsVbr_2 = *(_DWORD *)(NtfsVbr + 36); /*0xc0f*/
  NtfsVbr = NtfsVbr_2; /*0xc09*/
  BytesPerSectorVal = *(unsigned __int16 *)(NtfsVbr_1 + 11); /*0xc16*/
  CacheByteSize = NtfsVbr_2 * BytesPerSectorVal; /*0xc1f*/
  TotalSectorsVal = *(unsigned __int16 *)(NtfsVbr_1 + 19); /*0xc23*/
  if ( !(_WORD)TotalSectorsVal ) /*0xc2a*/
    TotalSectorsVal = *(_DWORD *)(NtfsVbr_1 + 32); /*0xc2c*/
  TotalSectorsVal_1 = TotalSectorsVal; /*0xc2f*/
  MftZoneSectors = (BytesPerSectorVal + 32 * *(unsigned __int16 *)(NtfsVbr_1 + 17) - 1) / BytesPerSectorVal; /*0xc47*/
  MftStartLba = *(unsigned __int16 *)(NtfsVbr_1 + 14); /*0xc49*/
  MftByteSize = MftZoneSectors * BytesPerSectorVal; /*0xc53*/
  ClustersPerMftRec = (TotalSectorsVal_1 - NtfsVbr * *(unsigned __int8 *)(NtfsVbr_1 + 16) - MftStartLba - MftZoneSectors) /*0xc64*/
                    / *(unsigned __int8 *)(NtfsVbr_1 + 13);
  MftOffset = MftStartLba * *(unsigned __int16 *)(NtfsVbr_1 + 11); /*0xc6f*/
  *(_QWORD *)(BootSector + 29) = MftOffset; /*0xc70*/
  DataOffset = NtfsVbr * *(unsigned __int16 *)(NtfsVbr_1 + 11) * *(unsigned __int8 *)(NtfsVbr_1 + 16); /*0xc83*/
  v13 = __CFADD__(*(_DWORD *)(BootSector + 29), DataOffset); /*0xc88*/
  *(_DWORD *)(BootSector + 37) = *(_DWORD *)(BootSector + 29) + DataOffset; /*0xc8b*/
  *(_DWORD *)(BootSector + 41) = HIDWORD(MftOffset) + v13; /*0xc92*/
  v13 = __CFADD__(*(_DWORD *)(BootSector + 37), MftByteSize); /*0xc97*/
  *(_DWORD *)(BootSector + 45) = *(_DWORD *)(BootSector + 37) + MftByteSize; /*0xc9a*/
  *(_DWORD *)(BootSector + 49) = *(_DWORD *)(BootSector + 41) + v13; /*0xca0*/
  *(_DWORD *)(BootSector + 53) = *(unsigned __int16 *)(NtfsVbr_1 + 11) * *(unsigned __int8 *)(NtfsVbr_1 + 13); /*0xcb2*/
  if ( ClustersPerMftRec < 0xFFF5 ) /*0xcba*/
    ClusterFactorVal = ClustersPerMftRec >= 0xFF5; /*0xcc8*/
  else
    ClusterFactorVal = 2; /*0xcbe*/
  CacheBufPtr = AllocBufPtr; /*0xcc9*/
  *(_BYTE *)(BootSector + 12) = ClusterFactorVal; /*0xcd3*/
  Index = *(unsigned __int16 *)(NtfsVbr_1 + 17); /*0xcdc*/
  Status = InitCache((int)CacheBufPtr, BootSector, CacheByteSize); /*0xce1*/
  if ( Status >= 0 ) /*0xce9*/
  {
    if ( !MftByteSize ) /*0xcf1*/
    {
      MftByteSize = WalkClusterChain(2, *(_DWORD *)(NtfsVbr_1 + 44), (char **)&NtfsVbr, 0) /*0xd06*/
                  * *(_DWORD *)(BootSector + 53);
      Index = MftByteSize >> 5; /*0xd10*/
    }
    i = i_1; /*0xd2a*/
    NtfsVbr = ((MftByteSize >> 12) + ((MftByteSize & 0xFFF) != 0)) << 12; /*0xd34*/
    if ( i_1 >= NtfsVbr ) /*0xd3a*/
    {
      AllocBufSize = i; /*0xd66*/
    }
    else
    {
      Status = (*(int (__cdecl **)(char *, int, unsigned int, char **))(*(_DWORD *)CacheBufPtr + 72))( /*0xd47*/
                 CacheBufPtr,
                 4,
                 (MftByteSize >> 12) + ((MftByteSize & 0xFFF) != 0),
                 &AllocBufPtr);
      if ( Status < 0 ) /*0xd4f*/
        return Status; /*0xd4f*/
      AllocBufSize = AllocBufPtr; /*0xd51*/
      i = NtfsVbr; /*0xd55*/
      i = AllocBufPtr; /*0xd59*/
      i_1 = NtfsVbr; /*0xd5f*/
    }
    ZeroMemEx(i, AllocBufSize, i, 0); /*0xd70*/
    if ( *(_BYTE *)(BootSector + 12) == 2 ) /*0xd87*/
      return ReadFileData((int)CacheBufPtr, BootSector, *(char **)(NtfsVbr_1 + 44), MftByteSize, (unsigned int)i); /*0xd8c*/
    else
      return ReadBlocks((int)CacheBufPtr, BootSector, *(_QWORD *)(BootSector + 37), MftByteSize, (unsigned int)i); /*0xd9c*/
  }
  return Status; /*0xda4*/
}


// Function: MountNtfsVolume @ 0xdac (0xcf bytes)
// Index: 20/77

int __fastcall MountNtfsVolume(char *BlockIoHandle, int BootSector, unsigned int *a3, unsigned int DstBuffer)
{
  int FileIdx; // esi
  int result; // eax
  unsigned int VbrBufPtr; // edi
  unsigned int NumFoundFiles; // edi
  int v10; // eax
  unsigned int EntrySize; // edx
  unsigned int NumFoundFiles_1; // [esp+14h] [ebp-8h] BYREF
  int BlockIoHandle_1; // [esp+18h] [ebp-4h]

  FileIdx = 0; /*0xdbd*/
  BlockIoHandle_1 = (int)BlockIoHandle; /*0xdcb*/
  result = ReadBlocks((int)BlockIoHandle, BootSector, 0, 0x200u, DataPtr + 512); /*0xdcf*/
  if ( result >= 0 ) /*0xdd9*/
  {
    VbrBufPtr = DataPtr + 512; /*0xde5*/
    if ( !(unsigned __int8)IsValidMbrPartition((char *)(DataPtr + 512)) ) /*0xded*/
      return -2147483634; /*0xded*/
    ::BootSector = BootSector; /*0xdf9*/
    result = ParseNtfsBootSector(BlockIoHandle, BootSector, VbrBufPtr); /*0xe01*/
    if ( result < 0 ) /*0xe09*/
      return result; /*0xe09*/
    LocateRecoveryInDir((int *)&NumFoundFiles_1); /*0xe11*/
    NumFoundFiles = NumFoundFiles_1; /*0xe16*/
    if ( NumFoundFiles_1 ) /*0xe1e*/
    {
      while ( 1 ) /*0xe24*/
      {
        v10 = dword_4F80[FileIdx]; /*0xe24*/
        EntrySize = *(_DWORD *)(v10 + 28); /*0xe2b*/
        if ( *a3 >= EntrySize /*0xe56*/
          && ReadFileData(
               BlockIoHandle_1,
               BootSector,
               (char *)(*(unsigned __int16 *)(v10 + 26) + (*(unsigned __int16 *)(v10 + 20) << 16)),
               EntrySize,
               DstBuffer) >= 0 )
        {
          break; /*0xe56*/
        }
        if ( ++FileIdx >= NumFoundFiles ) /*0xe5b*/
          return -2147483634; /*0xe5b*/
      }
      *a3 = *(_DWORD *)(dword_4F80[FileIdx] + 28); /*0xe74*/
      return 0; /*0xe77*/
    }
    else
    {
      return -2147483634; /*0xe5d*/
    }
  }
  return result; /*0xe62*/
}


// Function: MountVolume @ 0xe7b (0xd0 bytes)
// Index: 21/77

int __cdecl MountVolume(char *BlockIoHandle, int p_n4, unsigned int *a3, unsigned int ia)
{
  int result; // eax
  int PartResult; // ebx
  bool IsSuccess; // zf

  *(_DWORD *)(p_n4 + 21) = 0; /*0xe93*/
  *(_DWORD *)(p_n4 + 25) = 0; /*0xe96*/
  result = MountNtfsVolume(BlockIoHandle, p_n4, a3, ia); /*0xe99*/
  if ( result < 0 ) /*0xea2*/
  {
    result = ReadBlocks((int)BlockIoHandle, p_n4, 0, 0x200u, DataPtr); /*0xeba*/
    if ( result >= 0 ) /*0xec4*/
    {
      if ( *(_WORD *)(DataPtr + 510) == 0xAA55 ) /*0xed7*/
      {
        n4 = 0; /*0xed9*/
        LbaOffset = 0; /*0xedf*/
        dword_4D08 = 0; /*0xee5*/
        ExtendFlag = 1; /*0xeeb*/
        do /*0xefc*/
        {
          PartResult = ParsePartitionEntry((int)BlockIoHandle, p_n4); /*0xefc*/
          IsSuccess = PartResult == 0; /*0xefe*/
          if ( PartResult >= 0 ) /*0xf00*/
          {
            if ( byte_4BE8 && (!byte_4BCC || MatchFlag) ) /*0xf1b*/
            {
              result = MountNtfsVolume(BlockIoHandle, p_n4, a3, ia); /*0xf28*/
              if ( result >= 0 ) /*0xf31*/
              {
                byte_4BE8 = 0; /*0xf42*/
                return result; /*0xf42*/
              }
            }
            IsSuccess = PartResult == 0; /*0xf33*/
          }
        }
        while ( IsSuccess ); /*0xefc*/
      }
      return -2147483634; /*0xf37*/
    }
  }
  return result; /*0xf3c*/
}


// Function: ParseFatBootSector @ 0xf4b (0x168 bytes)
// Index: 22/77

int __fastcall ParseFatBootSector(int BlockIoPtr, int *p_n4, unsigned int *a3, unsigned int dst)
{
  int v6; // eax
  int result; // eax
  unsigned int VolumeSize_1; // edi
  int i; // eax
  unsigned int i_1; // esi
  char *BlockIoHandle; // ecx
  unsigned int NumEntries; // edi
  int EntryIdx; // esi
  int EntryAddr; // eax
  unsigned int SectorSize; // ecx
  unsigned int n4; // [esp-8h] [ebp-82Ch]
  int NumEntries_1; // [esp+10h] [ebp-814h] BYREF
  int BlockIoPtr_1; // [esp+14h] [ebp-810h]
  char *TmpBufPtr; // [esp+18h] [ebp-80Ch] BYREF
  _BYTE dst_1[158]; // [esp+20h] [ebp-804h] BYREF
  int v21; // [esp+BEh] [ebp-766h]
  unsigned int VolumeSize; // [esp+C6h] [ebp-75Eh]

  BlockIoPtr_1 = BlockIoPtr; /*0xf5d*/
  n4 = *p_n4; /*0xf66*/
  v6 = 16 * *p_n4; /*0xf68*/
  *(int *)((char *)p_n4 + 21) = 0; /*0xf6d*/
  *(int *)((char *)p_n4 + 25) = 0; /*0xf70*/
  result = ReadBlocks(BlockIoPtr, (int)p_n4, (unsigned int)v6, n4, (unsigned int)dst_1); /*0xf76*/
  if ( result < 0 ) /*0xf80*/
    return result; /*0xf80*/
  if ( dst_1[0] != 1 || AsciiStrCmp(&dst_1[1], "CD001", 5) ) /*0xf9c*/
    return -2147483634; /*0xfa4*/
  VolumeSize_1 = VolumeSize; /*0xfaa*/
  i = i_1; /*0xfc6*/
  i_1 = ((VolumeSize >> 12) + ((VolumeSize & 0xFFF) != 0)) << 12; /*0xfcd*/
  if ( i_1 >= i_1 ) /*0xfd2*/
  {
    BlockIoHandle = i; /*0x1001*/
  }
  else
  {
    result = (*(int (__cdecl **)(int, int, unsigned int, char **))(*(_DWORD *)BlockIoPtr + 72))( /*0xfe0*/
               BlockIoPtr,
               4,
               (VolumeSize >> 12) + ((VolumeSize & 0xFFF) != 0),
               &TmpBufPtr);
    if ( result < 0 ) /*0xfe8*/
      return result; /*0xfe8*/
    BlockIoHandle = TmpBufPtr; /*0xfee*/
    i = i_1; /*0xff2*/
    i = TmpBufPtr; /*0xff4*/
    i_1 = i_1; /*0xffa*/
  }
  ZeroMemEx(i, BlockIoHandle, i, 0); /*0x100b*/
  result = ReadBlocks(BlockIoPtr, (int)p_n4, (unsigned int)(v21 * *p_n4), VolumeSize_1, (unsigned int)i); /*0x102b*/
  if ( result >= 0 ) /*0x1035*/
  {
    ParseVolumeLabelEntries(VolumeSize_1, &NumEntries_1); /*0x103f*/
    NumEntries = NumEntries_1; /*0x1044*/
    if ( NumEntries_1 ) /*0x104c*/
    {
      EntryIdx = 0; /*0x104e*/
      while ( 1 ) /*0x105b*/
      {
        EntryAddr = dword_4CE0[EntryIdx]; /*0x105b*/
        SectorSize = *(_DWORD *)(EntryAddr + 10); /*0x1062*/
        if ( *a3 >= SectorSize /*0x108b*/
          && ReadBlocks(BlockIoPtr_1, (int)p_n4, (unsigned int)(*p_n4 * *(_DWORD *)(EntryAddr + 2)), SectorSize, dst) >= 0 )
        {
          break; /*0x108b*/
        }
        if ( ++EntryIdx >= NumEntries ) /*0x1090*/
          return -2147483634; /*0x1090*/
      }
      *a3 = *(_DWORD *)(dword_4CE0[EntryIdx] + 10); /*0x10ac*/
      return 0; /*0x10af*/
    }
    return -2147483634; /*0x1092*/
  }
  return result; /*0x1097*/
}


// Function: MountFatVolume @ 0x10b3 (0xe5 bytes)
// Index: 23/77

int __cdecl MountFatVolume(char *BlockIoHandle, int *p_n4, unsigned int *a3, unsigned int dst)
{
  int result; // eax
  int BootEntryOff; // eax
  char dst_; // [esp+8h] [ebp-800h] BYREF
  _BYTE v7[6]; // [esp+9h] [ebp-7FFh] BYREF
  _BYTE v8[33]; // [esp+Fh] [ebp-7F9h] BYREF
  int BootCatSector; // [esp+30h] [ebp-7D8h]
  int VoldescSector; // [esp+4Fh] [ebp-7B9h]

  if ( *p_n4 != 2048 ) /*0x10c9*/
    return -2147483645; /*0x118e*/
  result = ParseFatBootSector((int)BlockIoHandle, p_n4, a3, dst); /*0x10da*/
  if ( result < 0 ) /*0x10e3*/
  {
    result = ReadBlocks((int)BlockIoHandle, (int)p_n4, (unsigned int)(17 * *p_n4), *p_n4, (unsigned int)&dst_); /*0x10fc*/
    if ( result >= 0 ) /*0x1106*/
    {
      if ( dst_ || AsciiStrCmp(v7, "CD001", 5) || v7[5] != 1 || AsciiStrCmp(v8, "EL TORITO SPECIFICATION", 23) ) /*0x113a*/
      {
        return -2147483634; /*0x1187*/
      }
      else
      {
        result = ReadBlocks( /*0x1159*/
                   (int)BlockIoHandle,
                   (int)p_n4,
                   (unsigned int)(VoldescSector * *p_n4),
                   *p_n4,
                   (unsigned int)&dst_);
        if ( result >= 0 ) /*0x1163*/
        {
          BootEntryOff = BootCatSector * *p_n4; /*0x116d*/
          *(int *)((char *)p_n4 + 25) = 0; /*0x1172*/
          *(int *)((char *)p_n4 + 21) = BootEntryOff; /*0x117a*/
          return MountVolume(BlockIoHandle, (int)p_n4, a3, dst); /*0x117d*/
        }
      }
    }
  }
  return result; /*0x1193*/
}


// Function: FsRecoveryEntry @ 0x1198 (0xe3 bytes)
// Index: 24/77

int __fastcall FsRecoveryEntry(int *BlockIoHandle, int PartitionIdx, int a3, unsigned int *p_ImageSize, int dst)
{
  int result; // eax
  int SystemTable; // eax
  int AllocStatus; // ecx
  int MountIdx; // esi
  int (__cdecl **MountFuncPtr)(int, int *, unsigned int *, int); // eax
  unsigned int DataPtr; // [esp+10h] [ebp-54h] BYREF
  int v13; // [esp+18h] [ebp-4Ch] BYREF
  char v14; // [esp+1Ch] [ebp-48h]
  int v15; // [esp+24h] [ebp-40h]
  char buf[4]; // [esp+28h] [ebp-3Ch] BYREF
  int v17; // [esp+2Ch] [ebp-38h]
  int PartitionIdx_1; // [esp+30h] [ebp-34h]

  if ( !a3 || !p_ImageSize || *p_ImageSize && !dst ) /*0x11c5*/
    return -2147483646; /*0x126e*/
  ZeroMemEx((int)buf, buf, 0x39u, 0); /*0x11d4*/
  result = (*(int (__cdecl **)(int *, int, int, int *))(a3 + 4))(BlockIoHandle, a3, PartitionIdx, &v13); /*0x11e1*/
  if ( result >= 0 ) /*0x11e9*/
  {
    if ( v14 /*0x122c*/
      && (*(_DWORD *)buf = v15,
          dword_4F5C = v13,
          SystemTable = *BlockIoHandle,
          v17 = a3,
          PartitionIdx_1 = PartitionIdx,
          AllocStatus = (*(int (__cdecl **)(int *, int, int, unsigned int *))(SystemTable + 72))(
                          BlockIoHandle,
                          4,
                          1,
                          &DataPtr),
          AllocStatus >= 0) )
    {
      MountIdx = 0; /*0x1232*/
      DataPtr = DataPtr; /*0x1234*/
      if ( MountFatVolume ) /*0x1240*/
      {
        MountFuncPtr = &off_4300; /*0x1242*/
        do /*0x1265*/
        {
          AllocStatus = (*MountFuncPtr)((int)BlockIoHandle, (int *)buf, p_ImageSize, dst); /*0x1254*/
          if ( !AllocStatus ) /*0x125b*/
            break; /*0x125b*/
          ++MountIdx; /*0x125d*/
          MountFuncPtr = &off_4300 + MountIdx; /*0x125e*/
        }
        while ( *MountFuncPtr ); /*0x1265*/
      }
      return AllocStatus; /*0x126a*/
    }
    else
    {
      return -2147483634; /*0x11f6*/
    }
  }
  return result; /*0x1273*/
}


// Function: GetRecoveryImageConfig @ 0x127b (0xcf bytes)
// Index: 25/77

int __fastcall GetRecoveryImageConfig(int ecx0, _DWORD *a2, _DWORD *a3, _BYTE *a4)
{
  int DriverImageHandle; // eax
  int result; // eax
  int (__cdecl **v8)(_DWORD, __int16 *, void *, _DWORD, int *, void *); // [esp+Ch] [ebp-8h] BYREF
  int ConfigBufSize; // [esp+10h] [ebp-4h] BYREF

  ConfigBufSize = 560; /*0x1285*/
  DriverImageHandle = GetImageHandle(); /*0x128e*/
  result = (*(int (__cdecl **)(int, void *, _DWORD, _DWORD, int (__cdecl ***)(_DWORD, __int16 *, void *, _DWORD, int *, void *)))(*(_DWORD *)DriverImageHandle + 32))( /*0x12a3*/
             DriverImageHandle,
             &unk_4B00,
             0,
             0,
             &v8);
  if ( result >= 0 ) /*0x12ab*/
  {
    if ( (*v8)( /*0x12d1*/
           v8,
           aFlashupdateima, // "FlashUpdateImageName"
           &unk_4B40,
           0,
           &ConfigBufSize,
           &unk_4D20) < 0 )
    {
      if ( a2 ) /*0x1310*/
      {
        *a2 = "HR6N0.BIN"; /*0x1312*/
        byte_4BE9 = 0; /*0x1318*/
      }
      if ( a3 ) /*0x1324*/
        *a3 = 0x1000000; /*0x1326*/
      if ( a4 ) /*0x1331*/
        *a4 = 0; /*0x1333*/
      return ValidateRecoveryParams(ecx0, a2, a3, a4); /*0x133c*/
    }
    else
    {
      if ( a2 ) /*0x12d5*/
        *a2 = &unk_4D4A; /*0x12d7*/
      if ( a3 ) /*0x12e2*/
        *a3 = dword_4F4C; /*0x12e9*/
      if ( a4 ) /*0x12f0*/
        *a4 = 0; /*0x12f2*/
      byte_4BE9 = 1; /*0x12f5*/
      byte_4BCC = 1; /*0x12fe*/
      byte_4BC0 = 1; /*0x1305*/
      return 0; /*0x12fc*/
    }
  }
  return result; /*0x1343*/
}


// Function: GetRecoveryCaps @ 0x134a (0x17 bytes)
// Index: 26/77

int __cdecl GetRecoveryCaps(int a1, int a2, _DWORD *a3)
{
  if ( !a3 ) /*0x1350*/
    return -2147483646; /*0x1352*/
  *a3 = 1; /*0x1358*/
  return 0; /*0x1357*/
}


// Function: GetRecoveryImageInfo @ 0x1361 (0x4a bytes)
// Index: 27/77

int __cdecl GetRecoveryImageInfo(int a1, int a2, int a3, _DWORD *a4, _DWORD *a5)
{
  int result; // eax

  if ( !a4 ) /*0x1368*/
    return -2147483646; /*0x136a*/
  if ( a3 ) /*0x1375*/
    return -2147483634; /*0x1377*/
  result = GetRecoveryImageConfig(a1, 0, a4, 0); /*0x1388*/
  if ( result >= 0 ) /*0x1391*/
  {
    if ( a5 ) /*0x1399*/
    {
      *a5 = unk_4220; /*0x13a1*/
      a5[1] = unk_4224; /*0x13a2*/
      a5[2] = unk_4228; /*0x13a3*/
      a5[3] = unk_422C; /*0x13a4*/
    }
    return 0; /*0x13a6*/
  }
  return result; /*0x136f*/
}


// Function: FindRecoveryImage @ 0x13ab (0x148 bytes)
// Index: 28/77

int __cdecl FindRecoveryImage(int *i, int a2, int a3, int dst)
{
  int result; // eax
  int HandleIdx; // ebx
  int PartitionIdx; // edi
  unsigned int RetryCount; // ebx
  int RecoveryResult; // eax
  unsigned int ImageSize; // ebp
  int TmpResult; // [esp-10h] [ebp-34h]
  char v11; // [esp+7h] [ebp-1Dh] BYREF
  unsigned int ImageSize_1; // [esp+8h] [ebp-1Ch] BYREF
  int (__cdecl **v13)(int *, _DWORD, unsigned int *); // [esp+Ch] [ebp-18h] BYREF
  unsigned __int16 *v14; // [esp+10h] [ebp-14h] BYREF
  unsigned int ImageSize_2; // [esp+14h] [ebp-10h] BYREF
  unsigned int NumPartitions; // [esp+18h] [ebp-Ch] BYREF
  int HandleIdx_1; // [esp+1Ch] [ebp-8h]
  _BYTE v18[4]; // [esp+20h] [ebp-4h] BYREF

  DebugLogPrint(-1, (int)i, "..BLOCK DEVICE.."); /*0x13bb*/
  if ( !dst ) /*0x13c8*/
    return -2147483646; /*0x13ca*/
  if ( a3 ) /*0x13d9*/
    return -2147483634; /*0x13db*/
  result = GetRecoveryImageConfig((int)i, 0, &ImageSize_2, &v11); /*0x13f3*/
  if ( result >= 0 ) /*0x13fc*/
  {
    result = (*(int (__cdecl **)(int *, void *, _DWORD, _BYTE *, int (__cdecl ***)(int *, _DWORD, unsigned int *)))(*i + 32))( /*0x1419*/
               i,
               &unk_4B20,
               0,
               v18,
               &v13);
    for ( HandleIdx = 1; ; ++HandleIdx ) /*0x1421*/
    {
      HandleIdx_1 = HandleIdx; /*0x14db*/
      if ( result < 0 ) /*0x14e1*/
        break; /*0x14e1*/
      if ( (*v13)(i, v13, &NumPartitions) >= 0 && NumPartitions ) /*0x1444*/
      {
        PartitionIdx = 0; /*0x1446*/
        while ( 2 ) /*0x1448*/
        {
          RetryCount = 0; /*0x1448*/
          ImageSize_1 = ImageSize_2; /*0x144e*/
          do /*0x14b4*/
          {
            RecoveryResult = FsRecoveryEntry(i, PartitionIdx, (int)v13, &ImageSize_1, dst); /*0x1463*/
            if ( RecoveryResult == -2147483646 ) /*0x1470*/
              break; /*0x1470*/
            if ( RecoveryResult >= 0 ) /*0x1474*/
            {
              ImageSize = ImageSize_1; /*0x147c*/
              if ( (*(int (__cdecl **)(int *, unsigned __int16 **))(*i + 48))(i, &v14) < 0 /*0x1496*/
                || FindBootEntry(TmpResult, &v14) >= 0 )
              {
                *(_DWORD *)((char *)v14 + 37) = ImageSize; /*0x149c*/
              }
              if ( v11 || ImageSize_1 == ImageSize_2 ) /*0x14ae*/
                return 0; /*0x14e9*/
            }
            ++RetryCount; /*0x14b0*/
          }
          while ( RetryCount < 3 ); /*0x14b4*/
          if ( ++PartitionIdx <= NumPartitions ) /*0x14bb*/
            continue; /*0x14bb*/
          break;
        }
        HandleIdx = HandleIdx_1; /*0x14bd*/
      }
      result = (*(int (__cdecl **)(int *, void *, int, _BYTE *, int (__cdecl ***)(int *, _DWORD, unsigned int *)))(*i + 32))( /*0x14d4*/
                 i,
                 &unk_4B20,
                 HandleIdx,
                 v18,
                 &v13);
    }
  }
  return result; /*0x14ee*/
}


// Function: ParseVolumeLabelEntries @ 0x14f3 (0x90 bytes)
// Index: 29/77

char __usercall ParseVolumeLabelEntries@<al>(unsigned int TotalSize@<edx>, int *p_NumEntries)
{
  int SystemTable; // ecx
  char *VolumeLabelEntry; // esi
  unsigned int TotalSize_1; // ebx
  int *p_NumEntries_1; // edi
  int RecoveryImageConfig; // eax
  char *NextEntry; // ecx
  unsigned int SemicolonOff; // edx
  int NumEntries; // eax
  int SemicolonOff_1; // [esp-8h] [ebp-1Ch]
  char *v13; // [esp+10h] [ebp-4h] BYREF

  SystemTable = SystemTable; /*0x14f4*/
  VolumeLabelEntry = i; /*0x1501*/
  TotalSize_1 = 0; /*0x1507*/
  p_NumEntries_1 = p_NumEntries; /*0x150a*/
  *p_NumEntries = 0; /*0x1516*/
  RecoveryImageConfig = GetRecoveryImageConfig(SystemTable, &v13, &p_NumEntries, 0); /*0x1518*/
  if ( RecoveryImageConfig >= 0 && TotalSize ) /*0x1525*/
  {
    do /*0x1527*/
    {
      LOBYTE(RecoveryImageConfig) = *VolumeLabelEntry; /*0x1527*/
      NextEntry = VolumeLabelEntry + 33; /*0x1529*/
      LOBYTE(p_NumEntries) = RecoveryImageConfig; /*0x152c*/
      if ( !(_BYTE)RecoveryImageConfig ) /*0x1532*/
        break; /*0x1532*/
      SemicolonOff = 0; /*0x1534*/
      if ( *NextEntry != 59 ) /*0x1539*/
      {
        do /*0x1548*/
        {
          if ( SemicolonOff >= (unsigned __int8)VolumeLabelEntry[32] ) /*0x1541*/
            break; /*0x1541*/
          ++SemicolonOff; /*0x1543*/
        }
        while ( NextEntry[SemicolonOff] != 59 ); /*0x1548*/
      }
      if ( *v13 ) /*0x154e*/
      {
        SemicolonOff_1 = SemicolonOff; /*0x1554*/
        LOBYTE(SemicolonOff) = 0; /*0x1555*/
        if ( MatchNameWildcard(NextEntry, SemicolonOff, SemicolonOff_1, v13) >= 0 ) /*0x1560*/
        {
          NumEntries = *p_NumEntries_1; /*0x1571*/
          dword_4CE0[NumEntries] = (int)VolumeLabelEntry; /*0x1573*/
          RecoveryImageConfig = NumEntries + 1; /*0x157a*/
          *p_NumEntries_1 = RecoveryImageConfig; /*0x157b*/
          return RecoveryImageConfig; /*0x157b*/
        }
      }
      LOBYTE(RecoveryImageConfig) = (_BYTE)p_NumEntries; /*0x1562*/
      TotalSize_1 += (unsigned __int8)p_NumEntries; /*0x1567*/
      VolumeLabelEntry += (unsigned __int8)p_NumEntries; /*0x1569*/
    }
    while ( TotalSize_1 < TotalSize ); /*0x1527*/
  }
  return RecoveryImageConfig; /*0x157d*/
}


// Function: LocateRecoveryInDir @ 0x1583 (0x395 bytes)
// Index: 30/77

char __cdecl LocateRecoveryInDir(int *FoundIndexOut)
{
  int gSystemTable; // ecx
  char *DirEntriesBuf; // ebp
  unsigned int EntryIdx; // ebx
  int *FoundIndexOut_1; // edi
  char *Status; // eax
  char *i; // esi
  unsigned int PathLenW; // eax
  int v8; // edx
  int PathIdxW; // ecx
  int v10; // edx
  char *DirEntryPtr; // edi
  _WORD *v12; // edx
  unsigned int PathLenA; // eax
  int PathIdxA; // ecx
  unsigned int Index_1; // edi
  char *DirEntriesBuf_2; // ecx
  _WORD *v17; // edx
  unsigned int EntryIdx2_1; // edi
  int EntryOffset; // edi
  unsigned int ClusterSize; // esi
  int StartCluster; // ecx
  int CaseSensitive_1; // edx
  unsigned int EntryIdx2; // eax
  char *DirEntriesBuf_3; // ecx
  int FoundIdx; // eax
  unsigned int EntryWithExt; // ecx
  int CaseSensitive; // edx
  unsigned int TotalEntries; // esi
  int OutIndex; // eax
  char *DirEntriesBuf_1; // [esp+10h] [ebp-124h] BYREF
  char *RecoveryNamePtr; // [esp+14h] [ebp-120h] BYREF
  unsigned int Index; // [esp+18... [8544 chars total]


// Function: DispatchRead @ 0x1918 (0x47 bytes)
// Index: 31/77

int __cdecl DispatchRead(int a1)
{
  int v1; // ecx
  int v2; // edx
  unsigned int gDataPtr; // ebx
  int v4; // edi
  int (__cdecl *v5)(int, char, int, unsigned int); // eax
  int v6; // esi
  char gExtendFlag; // [esp+Ch] [ebp-8h]

  v2 = 0; /*0x1922*/
  gDataPtr = gDataPtr; /*0x1925*/
  gExtendFlag = gExtendFlag; /*0x192d*/
  v4 = v1; /*0x1930*/
  v5 = (int (__cdecl *)(int, char, int, unsigned int))dword_4BD4; /*0x1932*/
  v6 = 0; /*0x1937*/
  while ( v5 ) /*0x1954*/
  {
    v2 = v5(v4, gExtendFlag, a1, gDataPtr); /*0x1948*/
    v5 = (int (__cdecl *)(int, char, int, unsigned int))gCacheStruct[v6++]; /*0x194a*/
  }
  return v2; /*0x1956*/
}


// Function: ParsePartitionEntry @ 0x195f (0x2f7 bytes)
// Index: 32/77

int __fastcall ParsePartitionEntry(int BlockIo, int PartitionInfo)
{
  char HasExtendedParts; // al
  unsigned int PartIdx; // edx
  char PartitionType; // ch
  int LbaStartOffset; // ecx
  __int64 TempStart; // rax
  int Status; // eax
  int EntryOffset; // eax
  __int64 TempBlock; // rax
  bool IsBootable; // zf
  __int64 TempRead; // rax
  int GptSlotIdx; // edi
  __int64 v15; // rax
  unsigned int GptEntryPtr; // edi
  __int64 SizeResult; // rax
  int *ComparePtr; // edx
  char IsMatchingPart; // cl
  unsigned int OffsetValue; // edi
  int CmpLen; // esi
  __int64 TempSize; // rax
  int n4; // ecx
  unsigned int BlockBufPtr; // [esp-Ch] [ebp-20h]
  unsigned int DataPtr; // [esp-Ch] [ebp-20h]

  HasExtendedParts = ExtendFlag; /*0x1960*/
  PartIdx = n4; /*0x196c*/
  if ( ExtendFlag ) /*0x1977*/
  {
    if ( (unsigned int)n4 < 4 ) /*0x1980*/
    {
      while ( 1 ) /*0x1990*/
      {
        PartitionType = *(_BYTE *)(DataPtr + 16 * PartIdx + 450); /*0x1990*/
        if ( PartitionType == -18 ) /*0x199a*/
          break; /*0x199a*/
        if ( byte_4BCC ) /*0x19a7*/
          MatchFlag = *(_DWORD *)(DataPtr + 440) == dword_4D38 && n2 == 1; /*0x19cb*/
        if ( PartitionType == 5 || PartitionType == 15 ) /*0x19d8*/
        {
          LbaStartOffset = *(_DWORD *)(DataPtr + 16 * PartIdx + 454); /*0x19df*/
          if ( dword_4D08 ) /*0x19e8*/
            LbaStartOffset += dword_4D08; /*0x19f2*/
          else
            dword_4D08 = *(_DWORD *)(DataPtr + 16 * PartIdx + 454); /*0x19ea*/
          LbaOffset = LbaStartOffset; /*0x19f6*/
          TempStart = MultU64x32(512); /*0x1a02*/
          BlockBufPtr = DataPtr; /*0x1a07*/
          *(_QWORD *)(PartitionInfo + 21) = TempStart; /*0x1a1b*/
          Status = ReadBlocks(BlockIo, PartitionInfo, 0, 0x200u, BlockBufPtr); /*0x1a1e*/
          if ( Status < 0 ) /*0x1a28*/
            return Status; /*0x1a28*/
          PartIdx = 0; /*0x1a2e*/
          n4 = 0; /*0x1a30*/
        }
        EntryOffset = 16 * PartIdx; /*0x1a42*/
        if ( *(_BYTE *)(16 * PartIdx + DataPtr + 450) /*0x1a58*/
          && *(_DWORD *)(EntryOffset + DataPtr + 458)
          && *(_DWORD *)(EntryOffset + DataPtr + 454) )
        {
          TempSize = MultU64x32(512); /*0x1bfd*/
          n4 = n4 + 1; /*0x1c08*/
          *(_QWORD *)(PartitionInfo + 21) = TempSize; /*0x1c09*/
          n4 = n4; /*0x1c12*/
          goto LABEL_39; /*0x1c12*/
        }
        n4 = ++PartIdx; /*0x1a66*/
        if ( PartIdx >= 4 ) /*0x1a6f*/
        {
          HasExtendedParts = ExtendFlag; /*0x1a75*/
          goto LABEL_18; /*0x1a75*/
        }
      }
      ExtendFlag = 0; /*0x1c3a*/
      n4 = 0; /*0x1c40*/
LABEL_20:
      TempBlock = MultU64x32(1); /*0x1a8a*/
      Status = ReadBlocks(BlockIo, PartitionInfo, TempBlock, 0x200u, DataPtr); /*0x1aa5*/
      if ( Status < 0 ) /*0x1aaf*/
        return Status; /*0x1aaf*/
      if ( *(_BYTE *)DataPtr == 69 && *(_BYTE *)(DataPtr + 1) == 70 && *(_BYTE *)(DataPtr + 2) == 73 ) /*0x1ad2*/
      {
        IsBootable = *(_DWORD *)(DataPtr + 84) == 128; /*0x1ad8*/
        n4_0 = *(_DWORD *)(DataPtr + 80); /*0x1ae2*/
        if ( IsBootable ) /*0x1ae7*/
        {
          TempRead = MultU64x32(2); /*0x1af2*/
          Status = ReadBlocks(BlockIo, PartitionInfo, TempRead, 0x200u, DataPtr); /*0x1b08*/
          if ( Status < 0 ) /*0x1b12*/
            return Status; /*0x1b12*/
          PartIdx = n4; /*0x1b18*/
          goto LABEL_27; /*0x1b18*/
        }
      }
      return -2147483634; /*0x1c4b*/
    }
LABEL_18:
    if ( HasExtendedParts ) /*0x1a7c*/
      return -2147483634; /*0x1a7c*/
  }
  if ( !PartIdx ) /*0x1a84*/
    goto LABEL_20; /*0x1a84*/
LABEL_27:
  if ( PartIdx >= n4_0 ) /*0x1b24*/
    return -2147483634; /*0x1b24*/
  GptSlotIdx = PartIdx & 3; /*0x1b2c*/
  if ( (PartIdx & 3) == 0 && PartIdx ) /*0x1b33*/
  {
    v15 = MultU64x32((PartIdx >> 2) + 2); /*0x1b3f*/
    DataPtr = DataPtr; /*0x1b44*/
    *(_DWORD *)(PartitionInfo + 21) = 0; /*0x1b4c*/
    *(_DWORD *)(PartitionInfo + 25) = 0; /*0x1b58*/
    Status = ReadBlocks(BlockIo, PartitionInfo, v15, 0x200u, DataPtr); /*0x1b5b*/
    if ( Status < 0 ) /*0x1b65*/
      return Status; /*0x1b65*/
    PartIdx = n4; /*0x1b6b*/
  }
  GptEntryPtr = DataPtr + (GptSlotIdx << 7); /*0x1b77*/
  n4 = PartIdx + 1; /*0x1b7d*/
  SizeResult = MultU64x32(*(_QWORD *)(GptEntryPtr + 32)); /*0x1b89*/
  *(_QWORD *)(PartitionInfo + 21) = SizeResult; /*0x1b91*/
  if ( !SizeResult ) /*0x1b99*/
    return -2147483634; /*0x1b99*/
  if ( byte_4BCC )
  {
    ComparePtr = &dword_4D38; /*0x1baf*/
    IsMatchingPart = n2 == 2; /*0x1bbb*/
    OffsetValue = GptEntryPtr - (_DWORD)&dword_4D38; /*0x1bbe*/
    CmpLen = 16; /*0x1bc0*/
    do
    {
      IsMatchingPart = *((_BYTE *)ComparePtr + OffsetValue + 16) != *(_BYTE *)ComparePtr ? 0 : IsMatchingPart;
      ComparePtr = (int *)((char *)ComparePtr + 1); /*0x1bce*/
      --CmpLen; /*0x1bcf*/
    }
    while ( CmpLen );
    MatchFlag = IsMatchingPart; /*0x1bd4*/
  }
LABEL_39:
  if ( DispatchRead((unsigned __int8)dword_4F5C) >= 0 ) /*0x1c2b*/
    byte_4BE8 = 1; /*0x1c2d*/
  return 0; /*0x1c50*/
}


// Function: StrLen_Unicode @ 0x1c56 (0x80 bytes)
// Index: 33/77

unsigned int __fastcall StrLen_Unicode(_WORD *Str)
{
  _WORD *Str_1; // ebx
  int DebugLib; // eax
  int NullCheck; // eax
  unsigned int Length; // esi
  int DbgAssert; // eax

  Str_1 = Str; /*0x1c59*/
  if ( !Str ) /*0x1c63*/
  {
    DebugLib = GetDebugLib(); /*0x1c65*/
    if ( DebugLib ) /*0x1c6c*/
      (*(void (__cdecl **)(const char *, int, const char *))(DebugLib + 4))( /*0x1c79*/
        "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
        172,
        "String != ((void *) 0)");
  }
  if ( ((unsigned __int8)Str_1 & 1) != 0 ) /*0x1c82*/
  {
    NullCheck = GetDebugLib(); /*0x1c84*/
    if ( NullCheck ) /*0x1c8b*/
      (*(void (__cdecl **)(const char *, int, const char *))(NullCheck + 4))( /*0x1c98*/
        "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
        173,
        "((UINTN) String & 0x00000001) == 0");
  }
  Length = 0; /*0x1ca0*/
  while ( *Str_1 ) /*0x1ccd*/
  {
    if ( Length >= 0xF4240 ) /*0x1caa*/
    {
      DbgAssert = GetDebugLib(); /*0x1cac*/
      if ( DbgAssert ) /*0x1cb3*/
        (*(void (__cdecl **)(const char *, int, const char *))(DbgAssert + 4))( /*0x1cc0*/
          "e:\\hs\\MdePkg\\Library\\BaseLib\\String.c",
          181,
          "Length < _gPcd_FixedAtBuild_PcdMaximumUnicodeStringLength");
    }
    ++Str_1; /*0x1cc6*/
    ++Length; /*0x1cc9*/
  }
  return Length; /*0x1ccf*/
}


// Function: GetDebugLib @ 0x1cd6 (0x31 bytes)
// Index: 34/77

int GetDebugLib()
{
  int ImageHandle; // eax
  _BYTE v2[4]; // [esp+0h] [ebp-8h] BYREF
  int v3; // [esp+4h] [ebp-4h] BYREF

  ImageHandle = GetImageHandle(); /*0x1cdb*/
  if ( (*(int (__cdecl **)(int, void *, _DWORD, _BYTE *, int *))(*(_DWORD *)ImageHandle + 32))( /*0x1cfa*/
         ImageHandle,
         &unk_4B10,
         0,
         v2,
         &v3) >= 0 )
    return v3; /*0x1d00*/
  else
    return 0; /*0x1cfc*/
}


// Function: DebugPrint @ 0x1d07 (0x2a bytes)
// Index: 35/77

int DebugPrint(int n64, int FW_Capsule_Info_nDefault_Size_%X_n, ...)
{
  int result; // eax
  int (__cdecl **v3)(int, int, char *); // esi
  va_list va; // [esp+10h] [ebp+Ch] BYREF

  va_start(va, FW_Capsule_Info_nDefault_Size_%X_n);
  result = GetDebugLib(); /*0x1d08*/
  v3 = (int (__cdecl **)(int, int, char *))result; /*0x1d0d*/
  if ( result ) /*0x1d11*/
  {
    result = GetDebugPrintLevel(); /*0x1d13*/
    if ( (result & n64) != 0 ) /*0x1d1e*/
      return (*v3)(n64, FW_Capsule_Info_nDefault_Size_%X_n, (char *)va); /*0x1d2a*/
  }
  return result; /*0x1d2f*/
}


// Function: DebugAssert @ 0x1d31 (0x1e bytes)
// Index: 36/77

int __fastcall DebugAssert(int e:__hs__MdePkg__Library__BaseLib__X86ReadIdtr.c, int n37, int Idtr____((void__)_0))
{
  int result; // eax

  result = GetDebugLib(); /*0x1d37*/
  if ( result ) /*0x1d3e*/
    return (*(int (__cdecl **)(int, int, int))(result + 4))( /*0x1d46*/
             e:__hs__MdePkg__Library__BaseLib__X86ReadIdtr.c,
             n37,
             Idtr____((void__)_0));
  return result; /*0x1d4c*/
}


// Function: AsciiStrCmp @ 0x1d4f (0x62 bytes)
// Index: 37/77

int __fastcall AsciiStrCmp(_BYTE *a1, _BYTE *CD001, int n5)
{
  _BYTE *v3; // esi
  _BYTE *v4; // edi
  int n4; // ebx
  int v6; // ecx

  v3 = a1; /*0x1d56*/
  v4 = &a1[n5]; /*0x1d5a*/
  n4 = (unsigned __int8)a1 & 3; /*0x1d5c*/
  if ( ((unsigned __int8)a1 & 3) != 0 && n4 == ((unsigned __int8)CD001 & 3) ) /*0x1d68*/
  {
    v6 = 4 - n4; /*0x1d6d*/
    if ( n4 != 4 ) /*0x1d6f*/
    {
      do /*0x1d7c*/
      {
        if ( *v3 != *CD001 ) /*0x1d75*/
          break; /*0x1d75*/
        ++v3; /*0x1d77*/
        ++CD001; /*0x1d78*/
        --v6; /*0x1d79*/
      }
      while ( v6 ); /*0x1d7c*/
    }
  }
  while ( v3 <= v4 - 4 && *(_DWORD *)v3 == *(_DWORD *)CD001 ) /*0x1d87*/
  {
    v3 += 4; /*0x1d89*/
    CD001 += 4; /*0x1d8c*/
  }
  while ( 1 ) /*0x1d9d*/
  {
    if ( v3 >= v4 ) /*0x1d9f*/
      return 0; /*0x1da6*/
    if ( *v3 != *CD001 ) /*0x1d99*/
      break; /*0x1d99*/
    ++v3; /*0x1d9b*/
    ++CD001; /*0x1d9c*/
  }
  return (char)*v3 - (char)*CD001; /*0x1da3*/
}


// Function: FindDirEntry @ 0x1db1 (0x37 bytes)
// Index: 38/77

int __fastcall FindDirEntry(int TmpResult, unsigned __int16 **a2)
{
  unsigned __int16 *v3; // ecx
  int n4; // eax

  if ( !a2 ) /*0x1db3*/
    return -2147483646; /*0x1db5*/
  v3 = *a2; /*0x1dbb*/
  if ( **a2 == 0xFFFF ) /*0x1dc6*/
    return -2147483634; /*0x1ddb*/
  while ( 1 ) /*0x1dcc*/
  {
    v3 = (unsigned __int16 *)((char *)v3 + v3[1]); /*0x1dcc*/
    n4 = *v3; /*0x1dce*/
    if ( n4 == 4 ) /*0x1dd4*/
      break; /*0x1dd4*/
    if ( (_WORD)n4 == 0xFFFF ) /*0x1dd9*/
      return -2147483634; /*0x1dd9*/
  }
  *a2 = v3; /*0x1de2*/
  return 0; /*0x1dba*/
}


// Function: FindBootEntry @ 0x1de8 (0x49 bytes)
// Index: 39/77

int __fastcall FindBootEntry(int TmpResult, unsigned __int16 **a2)
{
  unsigned __int16 *v3; // edi
  int v4; // eax
  int result; // eax
  int TmpResult_1; // [esp-4h] [ebp-10h]
  unsigned __int16 *v7; // [esp+8h] [ebp-4h] BYREF

  if ( !a2 ) /*0x1df2*/
    return -2147483646; /*0x1e26*/
  v7 = *a2; /*0x1df6*/
  while ( 1 ) /*0x1e15*/
  {
    result = FindDirEntry(TmpResult, &v7); /*0x1e15*/
    if ( result < 0 ) /*0x1e1c*/
      break; /*0x1e1c*/
    v3 = v7; /*0x1dfb*/
    v4 = AsciiStrCmp((_BYTE *)v7 + 8, CD001, 16); /*0x1e08*/
    TmpResult = TmpResult_1; /*0x1e0d*/
    if ( !v4 ) /*0x1e10*/
    {
      *a2 = v3; /*0x1e20*/
      return 0; /*0x1e24*/
    }
  }
  return result; /*0x1e2b*/
}


// Function: DebugLogPrint @ 0x1e31 (0x72 bytes)
// Index: 40/77

int DebugLogPrint(int a1, int a2, _BYTE *a3, ...)
{
  int result; // eax
  _BYTE *v4; // eax
  va_list va; // [esp+18h] [ebp+14h] BYREF

  va_start(va, a3);
  result = (*(int (__stdcall **)(int))(*(_DWORD *)a2 + 32))(a2); /*0x1e4a*/
  if ( result >= 0 ) /*0x1e52*/
  {
    if ( a2 ) /*0x1e5a*/
    {
      result = GetDebugPrintLevel(); /*0x1e5c*/
      if ( (result & a1) != 0 ) /*0x1e66*/
      {
        v4 = a3; /*0x1e68*/
        if ( *a3 ) /*0x1e6b*/
        {
          do /*0x1e8b*/
          {
            if ( *v4 == 37 ) /*0x1e73*/
            {
              if ( *++v4 == 115 ) /*0x1e7b*/
              {
                *v4 = 97; /*0x1e7d*/
              }
              else if ( *v4 == 71 ) /*0x1e85*/
              {
                *v4 = 103; /*0x1e87*/
              }
            }
            ++v4; /*0x1e8a*/
          }
          while ( *v4 ); /*0x1e8b*/
          v4 = a3; /*0x1e90*/
        }
        return (*(int (__cdecl **)(int, _BYTE *, char *))a2)(a1, v4, (char *)va); /*0x1e99*/
      }
    }
  }
  return result; /*0x1ea1*/
}


// Function: StrLen @ 0x1ea3 (0xe bytes)
// Index: 41/77

// (too small: 0xe bytes)


// Function: RShiftU64 @ 0x1eb1 (0x2d bytes)
// Index: 42/77

unsigned __int64 __cdecl RShiftU64(unsigned __int64 a1)
{
  unsigned __int8 n0x40; // cl
  unsigned __int64 v2; // rax

  v2 = a1; /*0x1ebb*/
  if ( n0x40 >= 0x40u ) /*0x1ec4*/
    return 0; /*0x1ec6*/
  if ( n0x40 >= 0x20u ) /*0x1ecf*/
    v2 = HIDWORD(a1); /*0x1ed1*/
  return v2 >> (n0x40 & 0x1F); /*0x1eda*/
}


// Function: LShiftU64 @ 0x1ede (0x2d bytes)
// Index: 43/77

__int64 __cdecl LShiftU64(__int64 a1)
{
  unsigned __int8 n0x40; // cl
  __int64 v2; // rax

  v2 = a1; /*0x1ee8*/
  if ( n0x40 >= 0x40u ) /*0x1ef1*/
    return 0; /*0x1ef3*/
  if ( n0x40 >= 0x20u ) /*0x1efc*/
  {
    HIDWORD(v2) = a1; /*0x1efe*/
    LODWORD(v2) = 0; /*0x1f00*/
  }
  return v2 << (n0x40 & 0x1F); /*0x1f07*/
}


// Function: MultU64x32 @ 0x1f0b (0x28 bytes)
// Index: 44/77

__int64 __cdecl MultU64x32(__int64 a1)
{
  unsigned int v1; // ecx

  return a1 * v1; /*0x1f2f*/
}


// Function: IsValidNtfsVbr @ 0x1f33 (0x50 bytes)
// Index: 45/77

char __thiscall IsValidNtfsVbr(char *this)
{
  char v1; // dl

  v1 = 0; /*0x1f33*/
  if ( !*(this + 16) /*0x1f7b*/
    && !*(_WORD *)(this + 19)
    && !*((_DWORD *)this + 8)
    && *((_QWORD *)this + 5)
    && *(this + 3) == 78
    && *(this + 4) == 84
    && *(this + 5) == 70
    && *(this + 6) == 83
    && *((_WORD *)this + 255) == 0xAA55
    && (*this == -21 || *this == -23) )
  {
    return 1; /*0x1f7f*/
  }
  return v1; /*0x1f82*/
}


// Function: VerifyFileRecord @ 0x1f83 (0x8f bytes)
// Index: 46/77

int __fastcall VerifyFileRecord(_DWORD *MftRef, int ia)
{
  _WORD *v3; // ecx
  int v4; // esi
  _WORD *v6; // edi
  _WORD *v7; // edx

  if ( (*(_BYTE *)ia != 70 || *(_BYTE *)(ia + 1) != 73 || *(_BYTE *)(ia + 2) != 76 || *(_BYTE *)(ia + 3) != 69) /*0x1fb4*/
    && (*(_BYTE *)ia != 73 || *(_BYTE *)(ia + 1) != 78 || *(_BYTE *)(ia + 2) != 68 || *(_BYTE *)(ia + 3) != 88) )
  {
    return -2147483634; /*0x2009*/
  }
  v3 = (_WORD *)(ia + *(unsigned __int16 *)(ia + 4)); /*0x1fbe*/
  v4 = (unsigned __int16)(*(_WORD *)(ia + 6) - 1); /*0x1fc2*/
  if ( !*v3 ) /*0x1fc5*/
    return 0; /*0x1fcb*/
  v6 = v3 + 1; /*0x1fcf*/
  v7 = (_WORD *)(ia + 510); /*0x1fd2*/
  while ( *v7 == *v3 ) /*0x1fde*/
  {
    v4 += 0xFFFF; /*0x1fe3*/
    *v7 = *v6++; /*0x1fe9*/
    v7 += *MftRef >> 1; /*0x1ff3*/
    if ( !(_WORD)v4 ) /*0x1ff9*/
    {
      *v3 = 0; /*0x1ffd*/
      return 0; /*0x2000*/
    }
  }
  return -2147483638; /*0x200e*/
}


// Function: DecodeCompressedRun @ 0x2012 (0x127 bytes)
// Index: 47/77

int __fastcall DecodeCompressedRun(int *p_ia, _DWORD *p_i, int *p_n5)
{
  _BYTE *ia; // esi
  unsigned int v4; // ecx
  __int64 v5; // kr08_8
  unsigned __int8 n8; // bl
  unsigned __int8 v8; // bh
  _BYTE *v9; // esi
  unsigned __int8 *v10; // edi
  unsigned int v11; // ebp
  __int64 v12; // kr00_8
  int v13; // eax
  unsigned __int8 n8_1; // bh
  unsigned __int8 *v15; // esi
  char v16; // al
  int v17; // esi
  unsigned __int64 v18; // rax
  unsigned int v19; // ecx
  unsigned __int8 v20; // [esp+13h] [ebp-21h]
  char v21; // [esp+13h] [ebp-21h]
  int v22; // [esp+14h] [ebp-20h]
  int v23; // [esp+20h] [ebp-14h]
  int v24; // [esp+28h] [ebp-Ch]

  ia = (_BYTE *)*p_ia; /*0x2024*/
  v4 = 0; /*0x2026*/
  v23 = 0; /*0x202b*/
  v22 = 0; /*0x202f*/
  v5 = 0; /*0x2041*/
  if ( !*ia ) /*0x2035*/
    return -2147483617; /*0x2043*/
  n8 = *ia >> 4; /*0x204f*/
  v8 = *ia & 0xF; /*0x2052*/
  v9 = ia + 1; /*0x2055*/
  v20 = v8; /*0x2056*/
  if ( v8 ) /*0x2060*/
  {
    v10 = &v9[v8 - 1]; /*0x2068*/
    v11 = 0; /*0x206a*/
    do /*0x2087*/
    {
      v12 = *v10 + LShiftU64(__SPAIR64__(v11, v4)); /*0x2081*/
      v11 = HIDWORD(v12); /*0x2081*/
      v4 = v12; /*0x2081*/
      --v10; /*0x2083*/
      --v8; /*0x2084*/
    }
    while ( v8 ); /*0x2087*/
    v8 = v20; /*0x208d*/
    v22 = HIDWORD(v12); /*0x2091*/
    v23 = v12; /*0x2097*/
    v5 = 0; /*0x2097*/
  }
  v13 = v8; /*0x209b*/
  n8_1 = n8; /*0x209e*/
  v24 = (int)&v9[v13 + n8]; /*0x20a7*/
  v15 = (unsigned __int8 *)(v24 - 1); /*0x20ab*/
  v16 = *(_BYTE *)(v24 - 1); /*0x20ae*/
  v21 = v16; /*0x20b0*/
  if ( n8 ) /*0x20b6*/
  {
    do /*0x20d3*/
    {
      v5 = *v15-- + LShiftU64(v5); /*0x20cc*/
      --n8_1; /*0x20d0*/
    }
    while ( n8_1 ); /*0x20d3*/
    v16 = v21; /*0x20d5*/
  }
  if ( v16 < 0 && n8 < 8u ) /*0x20e0*/
  {
    v17 = (unsigned __int8)(8 - n8); /*0x20e6*/
    LODWORD(v18) = 0; /*0x20e9*/
    v19 = 0; /*0x20ed*/
    do /*0x2105*/
    {
      v18 = RShiftU64(__PAIR64__(v19, v18)); /*0x20f3*/
      v19 = HIDWORD(v18) | 0xFF000000; /*0x20fc*/
      --v17; /*0x2102*/
    }
    while ( v17 ); /*0x2105*/
    v5 = __PAIR64__(v19 | HIDWORD(v5), (unsigned int)v18 | (unsigned int)v5); /*0x2109*/
  }
  *(_QWORD *)p_n5 += v5; /*0x2113*/
  *p_i = v23; /*0x211c*/
  p_i[1] = v22; /*0x2122*/
  *p_ia = v24; /*0x212d*/
  return 0; /*0x2131*/
}


// Function: FindAttrByType @ 0x2139 (0x2f bytes)
// Index: 48/77

int __fastcall FindAttrByType(int i, unsigned __int8 n0x20, _DWORD *p_i)
{
  int j; // esi
  int v4; // eax

  for ( j = i + *(unsigned __int16 *)(i + 20); ; j += v4 ) /*0x213e*/
  {
    if ( *(_BYTE *)j == n0x20 ) /*0x2155*/
    {
      *p_i = j; /*0x215b*/
      return 0; /*0x2160*/
    }
    if ( *(_BYTE *)j > n0x20 ) /*0x2142*/
      break; /*0x2142*/
    if ( *(_BYTE *)j == 0xFF ) /*0x2146*/
      break; /*0x2146*/
    v4 = *(_DWORD *)(j + 4); /*0x2148*/
    if ( !v4 ) /*0x214d*/
      break; /*0x214d*/
  }
  return -2147483634; /*0x215f*/
}


// Function: ReadFileRecord @ 0x2168 (0x1bb bytes)
// Index: 49/77

int __fastcall ReadFileRecord(
        int Volume,
        _DWORD *MftRef,
        int BootSector,
        unsigned int RecordNum,
        unsigned __int16 TotalRecords,
        _BYTE *OutBuffer)
{
  __int64 BlockAddr; // rax
  unsigned int BytesPerSector; // ecx
  int ClusterSize; // ebp
  unsigned int BlockAddr_1; // esi
  __int64 RunOffset; // rax
  unsigned int RunOffset_1; // edi
  unsigned int RunOffsetHi; // eax
  __int64 RunStart; // kr08_8
  unsigned __int64 RecordIndex; // kr18_8
  __int64 BlockAddr_2; // kr00_8
  __int64 RunOffset2; // rax
  unsigned int RunOffset2_1; // edi
  __int64 FinalOffset; // rax
  _DWORD *MftRefSaved; // ebp
  unsigned int ClusterSize_1; // [esp-10h] [ebp-58h]
  unsigned int RunOffsetHi_1; // [esp+14h] [ebp-34h]
  int p_ia; // [esp+18h] [ebp-30h] BYREF
  unsigned int SectorsPerCluster; // [esp+1Ch] [ebp-2Ch]
  unsigned __int64 RecordIndex_1; // [esp+20h] [ebp-28h]
  int ClusterBytes; // [esp+28h] [ebp-20h]
  unsigned int TotalRecords_1; // [esp+2Ch] [ebp-1Ch]
  _DWORD *MftRefCopy; // [esp+30h] [ebp-18h]
  int Volume_1; // [esp+34h] [ebp-14h]
  int VcnOffset[2]; // [esp+38h] [ebp-10h] BYREF
  __int64 RunLength; // [esp+40h] [ebp-8h] BYREF

  MftRefCopy = MftRef; /*0x216d*/
  VcnOffset[0] = 0; /*0x2171*/
  VcnOffset[1] = 0; /*0x2179*/
  Volume_1 = Volume; /*0x2188*/
  p_ia = gDataPtr + 1024; /*0x218d*/
  TotalRecords_1 = TotalRecords; /*0x219c*/
  DecodeCompressedRun(&p_ia, &RunLength, VcnOffset); /*0x21aa*/
  ClusterBytes = *(unsigned __int16 *)(BootSector + 11) * *(unsigned __int8 *)(BootSector + 13); /*0x21c6*/
  BlockAddr = MultU64x32(RunLength); /*0x21ca*/
  BytesPerSector = *(unsigned __int16 *)(BootSector + 11); /*0x21cf*/
  ClusterSize = 1024; /*0x21d3*/
  RunOffsetHi_1 = HIDWORD(BlockAddr); /*0x21db*/
  BlockAddr_1 = BlockAddr; /*0x21df*/
  if ( (unsigned __int16)BytesPerSector > 0x400u ) /*0x21e4*/
  {
    SectorsPerCluster = 1; /*0x21f2*/
    ClusterSize = BytesPerSector; /*0x21fa*/
  }
  else
  {
    SectorsPerCluster = 0x400 / BytesPerSector; /*0x21ec*/
  }
  RunOffset = MultU64x32(*(__int64 *)VcnOffset); /*0x2208*/
  RecordIndex_1 = 0; /*0x2214*/
  RunOffset_1 = RunOffset; /*0x221a*/
  RunOffsetHi = RunOffsetHi_1; /*0x221c*/
  RunStart = __PAIR64__(HIDWORD(RunOffset), RunOffset_1); /*0x2220*/
  RecordIndex = 0; /*0x2220*/
  do /*0x22b4*/
  {
    if ( RunOffsetHi || BlockAddr_1 ) /*0x222a*/
    {
      RunStart += SectorsPerCluster; /*0x228e*/
      RunOffsetHi = (__PAIR64__(RunOffsetHi, BlockAddr_1) - (unsigned int)ClusterSize) >> 32; /*0x2293*/
      BlockAddr_1 -= ClusterSize; /*0x2293*/
      LODWORD(RecordIndex_1) = ++RecordIndex; /*0x2299*/
      HIDWORD(RecordIndex_1) = HIDWORD(RecordIndex); /*0x22a0*/
    }
    else
    {
      if ( DecodeCompressedRun(&p_ia, &RunLength, VcnOffset) < 0 ) /*0x2243*/
        return -2147483634; /*0x2243*/
      BlockAddr_2 = MultU64x32(RunLength); /*0x2260*/
      BlockAddr_1 = BlockAddr_2; /*0x2260*/
      RunOffset2 = MultU64x32(*(__int64 *)VcnOffset); /*0x2270*/
      RunOffset2_1 = RunOffset2; /*0x2279*/
      RunOffsetHi = HIDWORD(BlockAddr_2); /*0x227b*/
      RunStart = __PAIR64__(HIDWORD(RunOffset2), RunOffset2_1); /*0x2288*/
      RecordIndex = RecordIndex_1; /*0x2288*/
    }
  }
  while ( RecordIndex < __PAIR64__(TotalRecords_1, RecordNum) ); /*0x22b4*/
  FinalOffset = MultU64x32(RunStart); /*0x22c4*/
  ClusterSize_1 = ClusterSize; /*0x22d2*/
  MftRefSaved = MftRefCopy; /*0x22d3*/
  if ( ReadBlocks(Volume_1, (int)MftRefCopy, FinalOffset, ClusterSize_1, (unsigned int)OutBuffer) >= 0 /*0x22fc*/
    && *OutBuffer == 70
    && OutBuffer[1] == 73
    && OutBuffer[2] == 76
    && OutBuffer[3] == 69 )
  {
    _ImageBase = RunStart; /*0x2304*/
    if ( VerifyFileRecord(MftRefSaved, (int)OutBuffer) >= 0 ) /*0x2310*/
      return 0; /*0x2314*/
  }
  return -2147483634; /*0x231b*/
}


// Function: ReadNonResidentAttr @ 0x2323 (0x11e bytes)
// Index: 50/77

int __fastcall ReadNonResidentAttr(int i, int MftRef, int BlockIo, int p_ia, unsigned int ia, int p_i)
{
  unsigned int v6; // ebp
  int result; // eax
  int p_i_1; // esi
  __int64 v9; // rax
  unsigned __int64 i_3; // rax
  unsigned __int64 i_2; // kr00_8
  __int64 v12; // rax
  __int64 v13; // rax
  unsigned int v14; // et0
  unsigned int v15; // [esp+10h] [ebp-24h]
  unsigned __int64 i_4; // [esp+1Ch] [ebp-18h]
  int p_n5[2]; // [esp+24h] [ebp-10h] BYREF
  __int64 i_1; // [esp+2Ch] [ebp-8h] BYREF

  v6 = 0; /*0x2330*/
  v15 = 0; /*0x2332*/
  p_n5[0] = 0; /*0x2336*/
  p_n5[1] = 0; /*0x233e*/
  result = DecodeCompressedRun(&p_ia, &i_1, p_n5); /*0x2350*/
  if ( result >= 0 ) /*0x2359*/
  {
    p_i_1 = p_i; /*0x235f*/
    while ( 1 ) /*0x2373*/
    {
      v9 = MultU64x32(i_1); /*0x2373*/
      i_3 = MultU64x32(v9); /*0x237e*/
      i_4 = i_3; /*0x238d*/
      i_2 = *(_QWORD *)p_i_1; /*0x239d*/
      if ( i_3 <= *(_QWORD *)p_i_1 ) /*0x239d*/
        i_2 = i_3; /*0x23a1*/
      v12 = MultU64x32(*(__int64 *)p_n5); /*0x23b3*/
      v13 = MultU64x32(v12); /*0x23c2*/
      if ( !i_2 ) /*0x23ce*/
        break; /*0x23ce*/
      if ( ReadBlocks(i, MftRef, v13, i_2, ia) < 0 /*0x241f*/
        || (ia += i_2, v14 = (i_2 + __PAIR64__(v15, v6)) >> 32,
                       v6 += i_2,
                       v15 = v14,
                       *(_QWORD *)p_i_1 -= i_2,
                       i_2 == i_4)
        && DecodeCompressedRun(&p_ia, &i_1, p_n5) < 0
        || !*(_QWORD *)p_i_1 )
      {
        *(_DWORD *)(p_i_1 + 4) = 0; /*0x242a*/
        *(_DWORD *)p_i_1 = v6; /*0x2430*/
        return 0; /*0x2432*/
      }
    }
    return -2147483638; /*0x2434*/
  }
  return result; /*0x2439*/
}


// Function: LoadAttrListRecord @ 0x2441 (0x7c bytes)
// Index: 51/77

int __fastcall LoadAttrListRecord(int i, _DWORD *MftRef, int BlockIo, _BYTE *ia, int n144, int a6, int *p_n5)
{
  unsigned int v8; // esi
  int n144_1; // eax
  unsigned int n5; // ebx
  int v12; // esi

  v8 = gDataPtr + 1664; /*0x244c*/
  n144_1 = *(_DWORD *)(gDataPtr + 1664); /*0x2457*/
  while ( n144 != n144_1 ) /*0x245d*/
  {
    v8 += *(unsigned __int16 *)(v8 + 4); /*0x2463*/
    a6 -= *(unsigned __int16 *)(v8 + 4); /*0x2469*/
    n144_1 = *(_DWORD *)v8; /*0x246b*/
    if ( !*(_DWORD *)v8 || !a6 ) /*0x2473*/
      return n144_1; /*0x2473*/
  }
  n5 = *(_DWORD *)(v8 + 16); /*0x247b*/
  v12 = *(_DWORD *)(v8 + 20); /*0x247e*/
  if ( n5 != *p_n5 || v12 != p_n5[1] ) /*0x2488*/
  {
    n144_1 = ReadFileRecord(i, MftRef, BlockIo, n5, v12, ia); /*0x2495*/
    if ( !n144_1 ) /*0x249f*/
    {
      *p_n5 = n5; /*0x24ab*/
      p_n5[1] = v12; /*0x24ad*/
      return DebugLogPrint(-1, i, "\nRecord %x loaded from attribute list\n", n5); /*0x24b0*/
    }
  }
  return n144_1; /*0x24b8*/
}


// Function: ReadNtfsDirectory @ 0x24bd (0x307 bytes)
// Index: 52/77

int __fastcall ReadNtfsDirectory(int Volume, _DWORD *MftRef_1, int BlockIo, int a4, int a5, char *Buffer)
{
  int BlockIo_1; // ebp
  char *Buffer_1; // edi
  int Status; // ebx
  int AttrListSize; // eax
  char *Buffer_2; // ebx
  char *AttrStart; // ecx
  unsigned int ResidentSize; // ebp
  int AttrStatus; // edi
  int v16; // ecx
  __int64 i; // kr00_8
  int RunResult; // eax
  __int64 Temp64; // rax
  unsigned __int64 TotalSize; // rax
  unsigned int NumPages; // edi
  int v22; // [esp-4h] [ebp-38h]
  char *AttrPtr; // [esp+14h] [ebp-20h] BYREF
  _DWORD *MftRef; // [esp+18h] [ebp-1Ch]
  int p_i[2]; // [esp+1Ch] [ebp-18h] BYREF
  int RunOffset; // [esp+24h] [ebp-10h] BYREF
  int ZeroInit; // [esp+28h] [ebp-Ch]
  char *AllocBuf; // [esp+2Ch] [ebp-8h] BYREF

  ZeroInit = 0; /*0x24c0*/
  BlockIo_1 = BlockIo; /*0x24c9*/
  Buffer_1 = Buffer; /*0x24cf*/
  RunOffset = 5; /*0x24dd*/
  MftRef = MftRef_1; /*0x24e4*/
  p_i[0] = (int)Buffer; /*0x24e8*/
  Status = ReadFileRecord(Volume, MftRef_1, BlockIo, 5u, 0, Buffer); /*0x24f1*/
  if ( Status < 0 )
  {
    DebugLogPrint(-1, Volume, "\nRead directory: record not found\n");
    return Status; /*0x250c*/
  }
  LOBYTE(Buffer) = 0; /*0x2515*/
  AttrPtr = Buffer_1; /*0x251d*/
  if ( FindAttrByType((int)Buffer_1, 0x20u, &AttrPtr) || AttrPtr[8] ) /*0x2533*/
  {
    Buffer_2 = Buffer; /*0x2570*/
  }
  else
  {
    AttrListSize = *((unsigned __int16 *)AttrPtr + 10); /*0x2538*/
    Buffer_2 = (char *)(*((_DWORD *)AttrPtr + 1) - AttrListSize); /*0x253f*/
    LOBYTE(Buffer) = 1; /*0x2541*/
    CopyMemEx(gDataPtr + 1664, &AttrPtr[AttrListSize], (unsigned int)Buffer_2); /*0x2555*/
    DebugLogPrint(-1, Volume, "\nAttribute list found, size is %x\n", Buffer_2); /*0x2566*/
  }
  byte_4C94 = 0; /*0x2579*/
  if ( (_BYTE)Buffer ) /*0x2580*/
    LoadAttrListRecord(Volume, MftRef, BlockIo, Buffer_1, 144, (int)Buffer_2, &RunOffset); /*0x2595*/
  AttrPtr = Buffer_1; /*0x25a1*/
  if ( !FindAttrByType((int)Buffer_1, 0x90u, &AttrPtr) )
  {
    AttrStart = &AttrPtr[*((unsigned __int16 *)AttrPtr + 10)]; /*0x25be*/
    ResidentSize = *((_DWORD *)AttrStart + 5); /*0x25c3*/
    AttrPtr = &AttrStart[*((_DWORD *)AttrStart + 4) + 16]; /*0x25cb*/
    if ( ResidentSize >= 0x58 )
    {
      DebugLogPrint(-1, Volume, "\nRead directory: resident part found\n");
      CopyMemEx(gDataPtr + 1408, AttrPtr, ResidentSize); /*0x25f4*/
      byte_4C94 = 1; /*0x25fc*/
      n0x58 = ResidentSize; /*0x2603*/
    }
    BlockIo_1 = BlockIo; /*0x2609*/
  }
  if ( (_BYTE)Buffer ) /*0x2612*/
    LoadAttrListRecord(Volume, MftRef, BlockIo_1, Buffer_1, 160, (int)Buffer_2, &RunOffset); /*0x2627*/
  AttrStatus = FindAttrByType((int)Buffer_1, 0xA0u, p_i); /*0x263d*/
  if ( AttrStatus >= 0 )
  {
    CopyMemEx(gDataPtr + 1280, (char *)(p_i[0] + *(unsigned __int16 *)(p_i[0] + 32)), 0x80u); /*0x2685*/
    RunOffset = 0; /*0x2691*/
    Buffer = (char *)(gDataPtr + 1280); /*0x269d*/
    ZeroInit = 0; /*0x26a3*/
    for ( i = 0; ; i += *(_QWORD *)p_i ) /*0x26a3*/
    {
      v22 = v16; /*0x26a7*/
      RunResult = DecodeCompressedRun((int *)&Buffer, p_i, &RunOffset); /*0x26b5*/
      v16 = v22; /*0x26bb*/
      if ( RunResult ) /*0x26be*/
        break; /*0x26be*/
    }
    Temp64 = MultU64x32(i); /*0x26d0*/
    TotalSize = MultU64x32(Temp64); /*0x26db*/
    *(_QWORD *)p_i = TotalSize; /*0x26f0*/
    if ( byte_4BC1 )
    {
      if ( TotalSize > (unsigned int)gAllocBufPtr ) /*0x276b*/
      {
        p_i[1] = 0; /*0x276d*/
        p_i[0] = gAllocBufPtr; /*0x2772*/
      }
    }
    else
    {
      NumPages = ((TotalSize & 0xFFF) != 0) + (unsigned int)RShiftU64(TotalSize); /*0x2715*/
      Status = (*(int (__cdecl **)(int, int, unsigned int, char **))(*(_DWORD *)Volume + 72))( /*0x2724*/
                 Volume,
                 4,
                 NumPages,
                 &AllocBuf);
      if ( Status < 0 )
      {
        DebugLogPrint(-1, Volume, "\nRead directory: can't allocate memory\n");
        return Status; /*0x2732*/
      }
      gTmpBufPtr = AllocBuf; /*0x2742*/
      gAllocBufPtr = NumPages << 12; /*0x2747*/
      ZeroMemEx((int)AllocBuf, AllocBuf, NumPages << 12, 0); /*0x274d*/
      byte_4BC1 = 1; /*0x2755*/
    }
    AttrStatus = ReadNonResidentAttr( /*0x2798*/
                   Volume,
                   (int)MftRef,
                   BlockIo_1,
                   gDataPtr + 1280,
                   (unsigned int)gTmpBufPtr,
                   (int)p_i);
    if ( AttrStatus < 0 )
      DebugLogPrint(-1, Volume, "\nRead directory: error reading dir file\n");
    n4096 = p_i[0]; /*0x27b5*/
  }
  else
  {
    DebugLogPrint(-1, Volume, "\nRead directory: no index allocation attribute\n");
    if ( byte_4C94 ) /*0x265d*/
      return 0; /*0x2665*/
  }
  return AttrStatus; /*0x27bc*/
}


// Function: ReadRootDir @ 0x27c4 (0xba bytes)
// Index: 53/77

int __fastcall ReadRootDir(int i, int MftRef, char *ia)
{
  int *ia_1; // edi
  __int64 v6; // rax
  __int64 v7; // rax
  int result; // eax
  int v9; // ecx
  __int64 v10; // [esp-20h] [ebp-434h]
  char iaa[1028]; // [esp+10h] [ebp-404h] BYREF

  ia_1 = (int *)ia; /*0x27d0*/
  v6 = MultU64x32(*((_QWORD *)ia + 6)); /*0x27e1*/
  v7 = MultU64x32(v6); /*0x27ec*/
  *(_QWORD *)(MftRef + 29) = v7; /*0x27f1*/
  HIDWORD(v10) = HIDWORD(v7); /*0x2805*/
  LODWORD(v10) = *(_DWORD *)(MftRef + 29); /*0x2806*/
  result = ReadBlocks(i, MftRef, v10, 0x400u, (unsigned int)iaa); /*0x280b*/
  if ( result >= 0 ) /*0x2815*/
  {
    ia = iaa; /*0x281f*/
    result = FindAttrByType((int)iaa, 0x80u, &ia); /*0x282c*/
    if ( result >= 0 ) /*0x2836*/
    {
      CopyMemEx(gDataPtr + 1024, &ia[*((unsigned __int16 *)ia + 16)], 0x100u); /*0x2852*/
      byte_4BC1 = 0; /*0x285a*/
      return ReadNtfsDirectory(i, (_DWORD *)MftRef, (int)ia_1, v9, v9, iaa); /*0x286f*/
    }
  }
  return result; /*0x2877*/
}


// Function: ReadNtfsRoot @ 0x287e (0x188 bytes)
// Index: 54/77

int __fastcall ReadNtfsRoot(int i, _DWORD *MftRef, _DWORD *a3, _BYTE *ia)
{
  int v4; // esi
  int result; // eax
  char *ia_1; // ecx
  int RootDir; // ebp
  unsigned int p_i_1; // eax
  int v11; // ecx
  int v12; // [esp-4h] [ebp-20h]
  int p_i; // [esp+10h] [ebp-Ch] BYREF
  int p_i_2[2]; // [esp+14h] [ebp-8h] BYREF

  v4 = 0; /*0x2895*/
  result = ReadBlocks(i, (int)MftRef, 0, 0x200u, gDataPtr + 512); /*0x289d*/
  if ( result >= 0 ) /*0x28a7*/
  {
    if ( !IsValidNtfsVbr((char *)(gDataPtr + 512)) ) /*0x28b5*/
    {
      DebugLogPrint(-1, i, "\nIsNTFS failed\n"); /*0x28c6*/
      return -2147483634; /*0x28ce*/
    }
    RootDir = ReadRootDir(i, (int)MftRef, ia_1); /*0x28e5*/
    if ( RootDir >= 0 ) /*0x28ea*/
    {
      ::MftRef = MftRef; /*0x2905*/
      FindBootablePartitions(v12, &p_i); /*0x290f*/
      p_i_1 = p_i; /*0x2914*/
      if ( !p_i ) /*0x291d*/
        return -2147483634; /*0x291d*/
      p_i = 0; /*0x2923*/
      while ( 1 ) /*0x292a*/
      {
        v11 = dword_4CA0[v4]; /*0x292a*/
        if ( __PAIR64__(p_i, *a3) >= *(_QWORD *)(v11 + 64) ) /*0x2943*/
          break; /*0x2943*/
        if ( ++v4 >= p_i_1 ) /*0x2948*/
          return -2147483634; /*0x2948*/
      }
      p_i = (int)ia; /*0x2956*/
      p_i_2[0] = *(_DWORD *)(v11 + 64); /*0x295d*/
      p_i_2[1] = *(_DWORD *)(v11 + 68); /*0x2965*/
      result = ReadFileRecord(i, MftRef, gDataPtr + 512, *(_DWORD *)v11, *(_WORD *)(v11 + 4), ia); /*0x297e*/
      if ( result >= 0 ) /*0x2988*/
      {
        result = FindAttrByType((int)ia, 0x80u, &p_i); /*0x2997*/
        if ( result >= 0 ) /*0x29a1*/
        {
          CopyMemEx(gDataPtr + 1280, (char *)(p_i + *(unsigned __int16 *)(p_i + 32)), 0x80u); /*0x29c2*/
          result = ReadNonResidentAttr(i, (int)MftRef, gDataPtr + 512, gDataPtr + 1280, (unsigned int)ia, (int)p_i_2); /*0x29e8*/
          if ( result >= 0 ) /*0x29f2*/
          {
            *a3 = p_i_2[0]; /*0x29fc*/
            return 0; /*0x29ff*/
          }
        }
      }
    }
    else
    {
      DebugLogPrint(-1, i, "\nRead root failed\n"); /*0x28f4*/
      return RootDir; /*0x28fc*/
    }
  }
  return result; /*0x28d3*/
}


// Function: ParseExt2Superblock @ 0x2a06 (0x21b bytes)
// Index: 55/77

char __fastcall ParseExt2Superblock(int DebugLevel, int DirData, int RemainingSize, char *FileName, int *FoundEntry)
{
  int DebugLevel_1; // eax
  char *FileName_1; // ebp
  int DirData_1; // esi
  int NameLen; // edx
  char SearchChar; // ch
  int EntryPtr; // edi
  unsigned int RemainingEntry; // ebx
  unsigned __int8 NameLen_1; // cl
  char *NameBufPtr; // ebp
  char *WideNameSrc; // esi
  int NameLen_2; // ebx
  char WideChar; // al
  int NrdNameLen; // edx
  unsigned int TotalEntrySz_1; // ebx
  unsigned __int8 NameLenNrd; // cl
  char *NameBufPtr_2; // ebp
  char *WideSrcNrd; // esi
  int NrdNameLen_1; // ebx
  char WideCharNrd; // al
  bool IsMatch; // zf
  unsigned int n4096; // eax
  int NrdNameLen_2; // [esp-8h] [ebp-130h]
  char *_nResident_file_found:_%s_n; // [esp-8h] [ebp-130h]
  char *FileName_2; // [esp-4h] [ebp-12Ch]
  char SearchChar_1; // [esp+13h] [ebp-115h]
  int n0x58; // [esp+14h] [ebp-114h]
  unsigned int TotalEntrySz; // [esp+14h] [ebp-114h]
  int DirData_2; // [esp+18h] [ebp-110h]
  unsigned __int16 EntrySize; // [esp+20h] [ebp-108h]
  unsigned __int16 NrdEntrySize; // [esp+20h] [ebp-108h]
  unsigned int TotalEntrySz_2; // [esp+24h] [ebp-104h]
  char NameBufPtr_1[256]; // [esp+28h] [ebp-100h] BYREF

  DebugLevel_1 = DebugLevel; /*0x2a13*/
  FileName_1 = FileName; /*0x2a17*/
  DirData_1 = DirData; /*0x2a1f*/
  DirData_2 = DirData; /*0x2a26*/
  if ( byte_4C94 )
  {
    DebugLogPrint(-1, DebugLevel, "\nEntering resident search\n"); /*0x2a38*/
    SearchChar = *FileName; /*0x2a46*/
    EntryPtr = gDataPtr + 1408; /*0x2a49*/
    RemainingEntry = n0x58; /*0x2a4f*/
    n0x58 = n0x58; /*0x2a55*/
    SearchChar_1 = *FileName; /*0x2a59*/
    while ( 1 )
    {
      NameLen_1 = *(_BYTE *)(EntryPtr + 80); /*0x2a5d*/
      LOBYTE(NameLen) = 0; /*0x2a60*/
      EntrySize = *(_WORD *)(EntryPtr + 8); /*0x2a66*/
      if ( NameLen_1 ) /*0x2a6c*/
      {
        NameLen = NameLen_1; /*0x2a6e*/
        NameBufPtr = NameBufPtr_1; /*0x2a71*/
        WideNameSrc = (char *)(EntryPtr + 82); /*0x2a75*/
        NameLen_2 = NameLen_1; /*0x2a78*/
        do /*0x2a86*/
        {
          WideChar = *WideNameSrc; /*0x2a7a*/
          WideNameSrc += 2; /*0x2a7c*/
          *NameBufPtr++ = WideChar; /*0x2a7f*/
          --NameLen_2; /*0x2a83*/
        }
        while ( NameLen_2 ); /*0x2a86*/
        DirData_1 = DirData_2; /*0x2a88*/
        FileName_1 = FileName; /*0x2a8c*/
        RemainingEntry = n0x58; /*0x2a93*/
      }
      NameBufPtr_1[(unsigned __int8)NameLen] = 0; /*0x2a9a*/
      if ( SearchChar )
      {
        LOBYTE(NameLen) = 0; /*0x2aa6*/
        if ( MatchNameWildcard(NameBufPtr_1, NameLen, NameLen_1, FileName_1) >= 0 )
        {
          FileName_2 = FileName_1; /*0x2bce*/
          _nResident_file_found:_%s_n = "\nResident file found: %s\n";
LABEL_30:
          *FoundEntry = EntryPtr; /*0x2bd4*/
          DebugLogPrint(-1, DebugLevel, _nResident_file_found:_%s_n, FileName_2); /*0x2be3*/
          return 1; /*0x2bed*/
        }
        SearchChar = SearchChar_1; /*0x2abd*/
      }
      RemainingEntry -= EntrySize; /*0x2ac8*/
      EntryPtr += EntrySize; /*0x2aca*/
      n0x58 = RemainingEntry; /*0x2acc*/
      if ( RemainingEntry < 0x58 ) /*0x2ad3*/
      {
        DebugLevel_1 = DebugLevel; /*0x2ad5*/
        break; /*0x2ad5*/
      }
    }
  }
  DebugLogPrint(-1, DebugLevel_1, "\nBeginning non-resident search\n"); /*0x2ad9*/
LABEL_13:
  if ( *(_BYTE *)DirData_1 == 73
    && *(_BYTE *)(DirData_1 + 1) == 78
    && *(_BYTE *)(DirData_1 + 2) == 68
    && *(_BYTE *)(DirData_1 + 3) == 88
    && VerifyFileRecord(MftRef, DirData_1) >= 0 )
  {
    TotalEntrySz_1 = *(_DWORD *)(DirData_1 + 28); /*0x2b25*/
    EntryPtr = *(_DWORD *)(DirData_1 + 24) + DirData_1 + 24; /*0x2b2e*/
    TotalEntrySz = TotalEntrySz_1; /*0x2b30*/
    TotalEntrySz_2 = TotalEntrySz_1; /*0x2b34*/
    if ( TotalEntrySz_1 >= 0x58 )
    {
      while ( 1 )
      {
        NrdEntrySize = *(_WORD *)(EntryPtr + 8); /*0x2b45*/
        if ( !NrdEntrySize ) /*0x2b4c*/
          break; /*0x2b4c*/
        LOBYTE(NrdNameLen) = *(_BYTE *)(EntryPtr + 80); /*0x2b52*/
        NameLenNrd = 0; /*0x2b55*/
        if ( (_BYTE)NrdNameLen ) /*0x2b59*/
        {
          NameLenNrd = *(_BYTE *)(EntryPtr + 80); /*0x2b5b*/
          NameBufPtr_2 = NameBufPtr_1; /*0x2b5e*/
          WideSrcNrd = (char *)(EntryPtr + 82); /*0x2b62*/
          NrdNameLen_1 = (unsigned __int8)NrdNameLen; /*0x2b65*/
          do /*0x2b73*/
          {
            WideCharNrd = *WideSrcNrd; /*0x2b67*/
            WideSrcNrd += 2; /*0x2b69*/
            *NameBufPtr_2++ = WideCharNrd; /*0x2b6c*/
            --NrdNameLen_1; /*0x2b70*/
          }
          while ( NrdNameLen_1 ); /*0x2b73*/
          DirData_1 = DirData_2; /*0x2b75*/
          TotalEntrySz_1 = TotalEntrySz; /*0x2b79*/
          FileName_1 = FileName; /*0x2b7d*/
        }
        IsMatch = *FileName_1 == 0; /*0x2b84*/
        NameBufPtr_1[NameLenNrd] = 0; /*0x2b8b*/
        if ( !IsMatch )
        {
          NrdNameLen_2 = (unsigned __int8)NrdNameLen; /*0x2b9a*/
          LOBYTE(NrdNameLen) = 0; /*0x2b9b*/
          if ( MatchNameWildcard(NameBufPtr_1, NrdNameLen, NrdNameLen_2, FileName_1) >= 0 )
          {
            FileName_2 = FileName_1; /*0x2c19*/
            _nResident_file_found:_%s_n = "\nNon-resident file found: %s\n";
            goto LABEL_30; /*0x2c1f*/
          }
        }
        TotalEntrySz_1 -= NrdEntrySize; /*0x2baf*/
        EntryPtr += NrdEntrySize; /*0x2bb1*/
        TotalEntrySz = TotalEntrySz_1; /*0x2bb3*/
        if ( TotalEntrySz_1 < 0x58 ) /*0x2bba*/
        {
          if ( TotalEntrySz_2 >= 0x1000 ) /*0x2bc5*/
            n4096 = (TotalEntrySz_2 + 256) & 0xFFFFFF00; /*0x2bf4*/
          else
            n4096 = 4096; /*0x2bc7*/
          DirData_1 += n4096; /*0x2bf9*/
          IsMatch = RemainingSize == n4096; /*0x2bfb*/
          RemainingSize -= n4096; /*0x2bfb*/
          DirData_2 = DirData_1; /*0x2c02*/
          if ( !IsMatch ) /*0x2c06*/
            goto LABEL_13; /*0x2c06*/
          return 0; /*0x2c06*/
        }
      }
    }
  }
  return 0; /*0x2c0e*/
}


// Function: FindBootablePartitions @ 0x2c21 (0xac bytes)
// Index: 56/77

int __cdecl FindBootablePartitions(int a1, int *p_i)
{
  int DebugLevel_1; // ecx
  int n4096; // ebx
  char *gTmpBufPtr; // ebp
  int DebugLevel; // esi
  int v7; // eax
  int i; // ecx
  int FoundEntry__1; // eax
  int FoundEntry_; // [esp+10h] [ebp-10Ch] BYREF
  char *src; // [esp+14h] [ebp-108h] BYREF
  int v12; // [esp+18h] [ebp-104h] BYREF
  char dst[256]; // [esp+1Ch] [ebp-100h] BYREF

  n4096 = n4096; /*0x2c28*/
  gTmpBufPtr = gTmpBufPtr; /*0x2c33*/
  DebugLevel = DebugLevel_1; /*0x2c44*/
  FoundEntry_ = 0; /*0x2c47*/
  *p_i = 0; /*0x2c4b*/
  if ( GetRecoveryImageConfig(DebugLevel_1, &src, &v12, 0) < 0 ) /*0x2c5b*/
    return DebugLogPrint(-1, DebugLevel, "\nGet info error\n"); /*0x2c62*/
  v7 = StrLen(src); /*0x2c68*/
  CopyMemEx((unsigned int)dst, src, v7 + 1); /*0x2c78*/
  if ( !ParseExt2Superblock(DebugLevel, (int)gTmpBufPtr, n4096, dst, &FoundEntry_) ) /*0x2c8c*/
    return DebugLogPrint(-1, DebugLevel, "\nRecovery file not found\n"); /*0x2cba*/
  i = *p_i; /*0x2c98*/
  FoundEntry__1 = FoundEntry_; /*0x2c9a*/
  *p_i = 1; /*0x2c9e*/
  dword_4CA0[i] = FoundEntry__1; /*0x2ca9*/
  return DebugLogPrint(-1, DebugLevel, "\nRecovery file found\n"); /*0x2cc2*/
}


// Function: ReadMbr @ 0x2ccd (0xd5 bytes)
// Index: 57/77

int __cdecl ReadMbr(int i, _DWORD *MftRef, _DWORD *a3, _BYTE *i_1)
{
  int result; // eax
  int Blocks; // ebx
  int v6; // ebx
  bool v7; // zf

  *(_DWORD *)((char *)MftRef + 21) = 0; /*0x2ce9*/
  *(_DWORD *)((char *)MftRef + 25) = 0; /*0x2cec*/
  result = ReadNtfsRoot(i, MftRef, a3, i_1); /*0x2cef*/
  if ( result < 0 ) /*0x2cf8*/
  {
    Blocks = ReadBlocks(i, (int)MftRef, 0, 0x200u, gDataPtr); /*0x2d14*/
    if ( Blocks >= 0 ) /*0x2d1b*/
    {
      if ( *(_WORD *)(gDataPtr + 510) == 0xAA55 ) /*0x2d42*/
      {
        gExtendFlag = 1; /*0x2d58*/
        gPartIdx = 0; /*0x2d5f*/
        gLbaOffset = 0; /*0x2d64*/
        ExtPartLbaOffset = 0; /*0x2d69*/
        do /*0x2d94*/
        {
          v6 = ParsePartitionEntry(i, (int)MftRef); /*0x2d77*/
          v7 = v6 == 0; /*0x2d79*/
          if ( v6 >= 0 ) /*0x2d7b*/
          {
            result = ReadNtfsRoot(i, MftRef, a3, i_1); /*0x2d87*/
            if ( result >= 0 ) /*0x2d90*/
              return result; /*0x2d90*/
            v7 = v6 == 0; /*0x2d92*/
          }
        }
        while ( v7 ); /*0x2d94*/
      }
      else
      {
        DebugLogPrint(-1, i, "\naa55 not found\n"); /*0x2d4c*/
      }
      return -2147483634; /*0x2d96*/
    }
    else
    {
      DebugLogPrint(-1, i, "\nRead MBR failed\n"); /*0x2d25*/
      return Blocks; /*0x2d2d*/
    }
  }
  return result; /*0x2d9b*/
}


// Function: ReadExt4Root @ 0x2da2 (0x21a bytes)
// Index: 58/77

int __fastcall ReadExt4Root(
        int *BlockIo,
        int MediaDesc,
        int Superblock,
        int Inode,
        unsigned int *BlockIndex,
        _DWORD *CurrentOffset)
{
  int MediaSaved; // ebp
  unsigned int v8; // esi
  unsigned int BlockSize; // ebx
  unsigned int EntriesPerBlock; // eax
  char IndirectionLevel; // cl
  int BlockAddr; // eax
  unsigned int v13; // ebp
  int BlockIoPtr; // edx
  int Status; // eax
  __int64 BlockOffset; // rax
  int BlockIoPtr2; // edx
  __int64 Offset2; // rax
  unsigned int EntPerBlk; // ecx
  unsigned int IndirIndex; // eax
  __int64 IndirOffset; // rax
  _DWORD AllocBuf[2]; // [esp+18h] [ebp-8h] BYREF
  unsigned int EntPerBlkSaved; // [esp+24h] [ebp+4h]

  MediaSaved = MediaDesc; /*0x2db4*/
  v8 = *BlockIndex; /*0x2dba*/
  BlockSize = 1024 << *(_DWORD *)(Superblock + 24); /*0x2dc3*/
  EntriesPerBlock = BlockSize >> 2; /*0x2dc7*/
  EntPerBlkSaved = BlockSize >> 2; /*0x2dca*/
  if ( *BlockIndex < 0xC ) /*0x2dd1*/
  {
    IndirectionLevel = n2_0; /*0x2dd3*/
    if ( !n2_0 ) /*0x2ddb*/
    {
      BlockAddr = *(_DWORD *)(Inode + 4 * v8 + 40); /*0x2de5*/
LABEL_26:
      *CurrentOffset = BlockAddr; /*0x2f91*/
      goto LABEL_27; /*0x2f95*/
    }
    goto LABEL_16; /*0x2ddb*/
  }
  v13 = EntriesPerBlock + 12; /*0x2dee*/
  if ( v8 < EntriesPerBlock + 12 ) /*0x2df3*/
  {
    IndirectionLevel = n2_0; /*0x2df9*/
    if ( n2_0 == 1 ) /*0x2e02*/
      goto LABEL_12; /*0x2e02*/
    BlockIoPtr = *BlockIo; /*0x2e08*/
    n2_0 = 1; /*0x2e10*/
    if ( (*(int (__cdecl **)(int *, int, unsigned int, _DWORD *))(BlockIoPtr + 72))( /*0x2e37*/
           BlockIo,
           4,
           (BlockSize >> 12) + ((BlockSize & 0xFFF) != 0),
           AllocBuf) < 0 )
    {
      DebugLogPrint(-1, (int)BlockIo, "\nCan't allocate block pages 1\n"); /*0x2e41*/
      return -2147483617; /*0x2e4e*/
    }
    dst = AllocBuf[0]; /*0x2e59*/
    BlockOffset = MultU64x32(*(unsigned int *)(Inode + 88)); /*0x2e67*/
    Status = ReadBlocks((int)BlockIo, MediaDesc, BlockOffset, BlockSize, dst); /*0x2e7b*/
    if ( Status < 0 ) /*0x2e85*/
      return Status; /*0x2e85*/
    EntriesPerBlock = BlockSize >> 2; /*0x2e8b*/
  }
  IndirectionLevel = n2_0; /*0x2e8f*/
LABEL_12:
  if ( v8 < v13 && IndirectionLevel == 1 ) /*0x2e9c*/
  {
    BlockAddr = *(_DWORD *)(dst + 4 * v8 - 48); /*0x2ea3*/
    goto LABEL_26; /*0x2ea7*/
  }
  MediaSaved = MediaDesc; /*0x2eac*/
LABEL_16:
  if ( v8 >= EntriesPerBlock + 12 ) /*0x2eb5*/
  {
    if ( IndirectionLevel != 2 ) /*0x2ebe*/
    {
      BlockIoPtr2 = *BlockIo; /*0x2ec0*/
      n2_0 = 2; /*0x2ec8*/
      if ( (*(int (__cdecl **)(int *, int, unsigned int, _DWORD *))(BlockIoPtr2 + 72))( /*0x2eef*/
             BlockIo,
             4,
             (BlockSize >> 12) + ((BlockSize & 0xFFF) != 0),
             AllocBuf) < 0 )
      {
        DebugLogPrint(-1, (int)BlockIo, "\nCan't allocate block pages 2\n"); /*0x2ef6*/
        return -2147483617; /*0x2ef6*/
      }
      dst_0 = AllocBuf[0]; /*0x2f01*/
      Offset2 = MultU64x32(*(unsigned int *)(Inode + 92)); /*0x2f0f*/
      Status = ReadBlocks((int)BlockIo, MediaSaved, Offset2, BlockSize, dst); /*0x2f21*/
      if ( Status < 0 ) /*0x2f2b*/
        return Status; /*0x2f2b*/
      if ( n2_0 != 2 ) /*0x2f38*/
        goto LABEL_27; /*0x2f38*/
    }
    EntPerBlk = BlockSize >> 2; /*0x2f3a*/
    IndirIndex = (v8 - 12) / EntPerBlkSaved; /*0x2f45*/
    if ( !((v8 - 12) % EntPerBlkSaved) ) /*0x2f45*/
    {
      IndirOffset = MultU64x32(*(unsigned int *)(dst + 4 * IndirIndex - 4)); /*0x2f5c*/
      Status = ReadBlocks((int)BlockIo, MediaDesc, IndirOffset, BlockSize, dst_0); /*0x2f70*/
      if ( Status < 0 ) /*0x2f7a*/
        return Status; /*0x2f7a*/
      EntPerBlk = BlockSize >> 2; /*0x2f7c*/
      IndirIndex = (v8 - 12) / EntPerBlkSaved; /*0x2f80*/
    }
    BlockAddr = *(_DWORD *)(dst_0 + 4 * (v8 - 12 - EntPerBlk * IndirIndex)); /*0x2f8e*/
    goto LABEL_26; /*0x2f8e*/
  }
LABEL_27:
  *BlockIndex = v8 + 1; /*0x2f97*/
  return *CurrentOffset != 0 ? 0 : -2147483617;
}


// Function: ReadExt4DirInode @ 0x2fbc (0x2b4 bytes)
// Index: 59/77

int __fastcall ReadExt4DirInode(
        int *BlockIo,
        int MediaDesc,
        int Superblock,
        _WORD *Inode,
        unsigned int Buffer,
        unsigned int *ReadSize)
{
  unsigned int TotalRead; // ebx
  _WORD *Inode_1; // eax
  unsigned int TotalHi; // edi
  int BlockIdx; // ecx
  int BlockIdx_1; // esi
  int ExtentOff; // edi
  __int64 StartBlock; // rax
  __int64 BlockAddr; // rax
  int v15; // ecx
  unsigned int ChunkSize; // esi
  int Status; // eax
  bool v18; // cf
  int RootResult; // esi
  __int64 BlockOffset; // rax
  bool v21; // zf
  int ReadStatus; // eax
  unsigned int NewTotal; // kr00_4
  unsigned int BlockGroupSz; // [esp+14h] [ebp-20h]
  __int64 CurrentOffset; // [esp+1Ch] [ebp-18h] BYREF
  unsigned int p_BlockIdx; // [esp+24h] [ebp-10h] BYREF
  int BlockOffHi; // [esp+28h] [ebp-Ch]
  int BlockOffset_1; // [esp+2Ch] [ebp-8h]
  int ReadStatus_1; // [esp+30h] [ebp-4h]
  int Superblocka; // [esp+38h] [ebp+4h]
  _WORD *Blocks; // [esp+3Ch] [ebp+8h]

  TotalRead = 0; /*0x2fd1*/
  p_BlockIdx = 0; /*0x2fd3*/
  BlockGroupSz = 1024 << *(_DWORD *)(Superblock + 24); /*0x2fe1*/
  Inode_1 = Inode; /*0x2fe5*/
  TotalHi = 0; /*0x2fea*/
  CurrentOffset = 0; /*0x2fec*/
  n2_0 = 0; /*0x2ff4*/
  if ( Inode[20] == 0xF30A && Inode[22] == 4 ) /*0x3009*/
  {
    LOWORD(BlockIdx) = 0; /*0x3013*/
    p_BlockIdx = (unsigned __int16)Inode[21]; /*0x3017*/
    Superblocka = 0; /*0x301b*/
    if ( !(_WORD)p_BlockIdx ) /*0x3022*/
      return -2147483638; /*0x30bc*/
    while ( 1 ) /*0x302c*/
    {
      BlockIdx_1 = (unsigned __int16)BlockIdx; /*0x302c*/
      ExtentOff = 6 * (unsigned __int16)BlockIdx; /*0x3031*/
      StartBlock = LShiftU64((unsigned __int16)Inode_1[ExtentOff + 29]); /*0x303c*/
      BlockAddr = MultU64x32(*(unsigned int *)&Inode[6 * BlockIdx_1 + 30] + StartBlock); /*0x3057*/
      ChunkSize = v15 * (unsigned __int16)Inode[ExtentOff + 28]; /*0x3064*/
      if ( *(_QWORD *)ReadSize <= (unsigned __int64)ChunkSize ) /*0x3071*/
        break; /*0x3071*/
      Status = ReadBlocks((int)BlockIo, MediaDesc, BlockAddr, ChunkSize, Buffer); /*0x3080*/
      if ( Status < 0 ) /*0x308a*/
        return Status; /*0x308a*/
      v18 = *ReadSize < ChunkSize; /*0x3090*/
      *ReadSize -= ChunkSize; /*0x3090*/
      ReadSize[1] -= v18; /*0x3096*/
      Inode_1 = Inode; /*0x309e*/
      CurrentOffset += ChunkSize; /*0x309a*/
      BlockIdx = Superblocka + 1; /*0x30a7*/
      Superblocka = BlockIdx; /*0x30a8*/
      if ( (unsigned __int16)BlockIdx >= (unsigned __int16)p_BlockIdx ) /*0x30b1*/
        return -2147483638; /*0x30b1*/
    }
    Status = ReadBlocks((int)BlockIo, MediaDesc, BlockAddr, *ReadSize, Buffer); /*0x30cf*/
    if ( Status < 0 ) /*0x30dd*/
    {
      *(_QWORD *)ReadSize = CurrentOffset; /*0x30df*/
      return Status; /*0x30e8*/
    }
    v18 = __CFADD__((_DWORD)CurrentOffset, *ReadSize); /*0x30ed*/
    *ReadSize += CurrentOffset; /*0x30ed*/
    ReadSize[1] += HIDWORD(CurrentOffset) + v18; /*0x30f3*/
  }
  else
  {
    RootResult = ReadExt4Root(BlockIo, MediaDesc, Superblock, (int)Inode, &p_BlockIdx, &CurrentOffset); /*0x310f*/
    if ( RootResult < 0 ) /*0x3116*/
    {
      *ReadSize = 0; /*0x3124*/
      ReadSize[1] = 0; /*0x3126*/
      DebugLogPrint(-1, (int)BlockIo, "\nFirst GetNextBlock failed\n"); /*0x3129*/
      return RootResult; /*0x3133*/
    }
    HIDWORD(CurrentOffset) = Buffer; /*0x3140*/
    while ( 1 ) /*0x314e*/
    {
      BlockOffset = MultU64x32(BlockGroupSz); /*0x314e*/
      BlockOffHi = HIDWORD(BlockOffset); /*0x3156*/
      v21 = ReadSize[1] == 0; /*0x315a*/
      BlockOffset_1 = BlockOffset; /*0x3160*/
      if ( v21 && *ReadSize <= BlockGroupSz ) /*0x3172*/
        break; /*0x3172*/
      ReadStatus = ReadBlocks((int)BlockIo, MediaDesc, BlockOffset, BlockGroupSz, HIDWORD(CurrentOffset)); /*0x3185*/
      ReadStatus_1 = ReadStatus; /*0x318d*/
      if ( ReadStatus < 0 ) /*0x3193*/
      {
        DebugLogPrint(-1, (int)BlockIo, "\nReading block failed, status = %r\n", ReadStatus); /*0x31fd*/
        DebugLogPrint( /*0x321a*/
          -1,
          (int)BlockIo,
          "\nOffset %lx, BlockSize %x, Block %x\n",
          BlockOffset_1,
          BlockOffHi,
          BlockGroupSz);
        return ReadStatus_1; /*0x3226*/
      }
      v18 = *ReadSize < BlockGroupSz; /*0x3199*/
      *ReadSize -= BlockGroupSz; /*0x3199*/
      ReadSize[1] -= v18; /*0x319f*/
      NewTotal = BlockGroupSz + TotalRead; /*0x31a6*/
      TotalHi = (__PAIR64__(TotalHi, BlockGroupSz) + TotalRead) >> 32; /*0x31a6*/
      TotalRead += BlockGroupSz; /*0x31a6*/
      HIDWORD(CurrentOffset) += BlockGroupSz; /*0x31ab*/
      if ( ReadExt4Root(BlockIo, MediaDesc, Superblock, (int)Inode, &p_BlockIdx, &CurrentOffset) < 0 ) /*0x31cb*/
      {
        DebugLogPrint(-1, (int)BlockIo, "\nGetNextBlock failed\n"); /*0x31e5*/
        *ReadSize = NewTotal; /*0x31ed*/
        ReadSize[1] = TotalHi; /*0x31ef*/
        return 0; /*0x31f2*/
      }
      if ( !*(_QWORD *)ReadSize ) /*0x31cd*/
        return -2147483638; /*0x31d2*/
    }
    Blocks = (_WORD *)ReadBlocks((int)BlockIo, MediaDesc, BlockOffset, *ReadSize, HIDWORD(CurrentOffset)); /*0x323e*/
    if ( (int)Blocks < 0 ) /*0x3244*/
    {
      DebugLogPrint(-1, (int)BlockIo, "\nReading partial block failed\n"); /*0x324e*/
      *ReadSize = TotalRead; /*0x325a*/
      ReadSize[1] = TotalHi; /*0x325c*/
      return (int)Blocks; /*0x325f*/
    }
    *(_QWORD *)ReadSize += __PAIR64__(TotalHi, TotalRead); /*0x3261*/
  }
  return 0; /*0x3268*/
}


// Function: ReadExt4BlockBitmap @ 0x3270 (0x1ec bytes)
// Index: 60/77

int __fastcall ReadExt4BlockBitmap(int *BlockIo, int MediaDesc, int Superblock)
{
  unsigned int OffsetBlocks; // esi
  int BlockSize; // ebp
  __int64 BaseAddr; // kr10_8
  int Status; // eax
  __int64 GroupOffset; // rdi
  __int64 BlockAddr; // rax
  unsigned int FileSizeLow; // ecx
  __int64 FileSizeLow_1; // rax
  unsigned int FileSize; // kr08_4
  unsigned int NumPages; // esi
  int AllocResult; // edi
  unsigned int BlocksPerGroup; // [esp+10h] [ebp-3Ch]
  unsigned __int64 gAllocBufPtr; // [esp+18h] [ebp-34h] BYREF
  char *AllocBuf; // [esp+20h] [ebp-2Ch] BYREF
  unsigned int EntryBuf[2]; // [esp+28h] [ebp-24h] BYREF
  int BgbtVal; // [esp+30h] [ebp-1Ch]

  OffsetBlocks = 0; /*0x3288*/
  BlockSize = 1024 << *(_DWORD *)(Superblock + 24); /*0x328e*/
  BaseAddr = MultU64x32((unsigned int)BlockSize); /*0x32a0*/
  LODWORD(gAllocBufPtr) = HIDWORD(BaseAddr); /*0x32a0*/
  BlocksPerGroup = 1; /*0x32aa*/
  if ( !*(_DWORD *)(Superblock + 40) ) /*0x32ae*/
  {
    BlocksPerGroup = 1u % *(_DWORD *)(Superblock + 40); /*0x32ba*/
    OffsetBlocks = 32 * (1u / *(_DWORD *)(Superblock + 40)); /*0x32be*/
  }
  if ( ReadBlocks( /*0x32e2*/
         (int)BlockIo,
         MediaDesc,
         __PAIR64__(gAllocBufPtr, BaseAddr) + OffsetBlocks,
         0x20u,
         (unsigned int)EntryBuf) < 0 )
  {
    DebugLogPrint(-1, (int)BlockIo, "\nRead BGBT error\n"); /*0x32ec*/
    return -2147483634; /*0x32f9*/
  }
  BgbtVal = BgbtVal; /*0x330c*/
  GroupOffset = MultU64x32(BlocksPerGroup); /*0x331c*/
  BlockAddr = MultU64x32((unsigned int)BlockSize); /*0x3323*/
  if ( ReadBlocks((int)BlockIo, MediaDesc, BlockAddr + GroupOffset, 0x80u, gDataPtr + 2432) < 0 ) /*0x3350*/
  {
    DebugLogPrint(-1, (int)BlockIo, "\nRead dir inode error. Inode is %x\n", 2); /*0x335c*/
    return -2147483634; /*0x3366*/
  }
  FileSizeLow_1 = LShiftU64(*(unsigned int *)(gDataPtr + 2540)); /*0x337b*/
  FileSizeLow = FileSizeLow_1; /*0x3382*/
  LODWORD(FileSizeLow_1) = gDataPtr; /*0x3384*/
  FileSize = *(_DWORD *)(gDataPtr + 2436); /*0x3389*/
  gAllocBufPtr = __PAIR64__(HIDWORD(FileSizeLow_1), FileSize) + FileSizeLow; /*0x338f*/
  if ( byte_4BC1 ) /*0x33a0*/
  {
    if ( __PAIR64__(HIDWORD(FileSizeLow_1), FileSize) + FileSizeLow > (unsigned int)gAllocBufPtr ) /*0x341f*/
      gAllocBufPtr = (unsigned int)gAllocBufPtr; /*0x3421*/
  }
  else
  {
    NumPages = ((((_WORD)FileSize + (_WORD)FileSizeLow) & 0xFFF) != 0) /*0x33b9*/
             + (unsigned int)RShiftU64(__PAIR64__(HIDWORD(FileSizeLow_1), FileSize) + FileSizeLow);
    AllocResult = (*(int (__cdecl **)(int *, int, unsigned int, char **))(*BlockIo + 72))( /*0x33c8*/
                    BlockIo,
                    4,
                    NumPages,
                    &AllocBuf);
    if ( AllocResult < 0 ) /*0x33cf*/
    {
      DebugLogPrint(-1, (int)BlockIo, "\nRead EXT dir allocate error\n"); /*0x33d9*/
      return AllocResult; /*0x33e3*/
    }
    gTmpBufPtr = AllocBuf; /*0x33f0*/
    gAllocBufPtr = NumPages << 12; /*0x33f5*/
    ZeroMemEx((int)AllocBuf, AllocBuf, NumPages << 12, 0); /*0x33fb*/
    LODWORD(FileSizeLow_1) = gDataPtr; /*0x3400*/
    byte_4BC1 = 1; /*0x3408*/
  }
  Status = ReadExt4DirInode( /*0x3442*/
             BlockIo,
             MediaDesc,
             Superblock,
             (_WORD *)(FileSizeLow_1 + 2432),
             (unsigned int)gTmpBufPtr,
             (unsigned int *)&gAllocBufPtr);
  n4096 = gAllocBufPtr; /*0x344b*/
  return Status; /*0x3454*/
}


// Function: ReadExt4FileData @ 0x345c (0x2cc bytes)
// Index: 61/77

int __fastcall ReadExt4FileData(int *BlockIo, int MediaDesc, unsigned int *FileSize, unsigned int ZeroCheck)
{
  int Status; // esi
  unsigned int i; // eax
  int BlockSize; // eax
  __int64 BaseAddr; // rax
  int EntryIndex; // ebp
  unsigned int AdjustedBlock; // esi
  int TableOffset; // ecx
  int TableSlot; // ecx
  __int64 BlockAddr; // rax
  unsigned __int64 BaseAddr_2; // kr08_8
  __int64 FileSizeHigh; // rax
  unsigned int FileSizeLow; // kr04_4
  unsigned int TotalFileSize; // kr10_4
  int DirResult; // eax
  int DirResult_1; // esi
  int Superblock; // [esp-4h] [ebp-58h]
  unsigned int AddrHi; // [esp+10h] [ebp-44h]
  unsigned int BaseAddr_1; // [esp+14h] [ebp-40h]
  unsigned int NumEntries; // [esp+18h] [ebp-3Ch] BYREF
  unsigned int AdjustedBlock_1; // [esp+1Ch] [ebp-38h]
  int BlockSize_1; // [esp+20h] [ebp-34h]
  int BlockGroupSz; // [esp+24h] [ebp-30h]
  __int64 ReadSize; // [esp+28h] [ebp-2Ch] BYREF
  char EntryBuf[8]; // [esp+30h] [ebp-24h] BYREF
  int BgbtVal; // [esp+38h] [ebp-1Ch]

  Status = ReadBlocks((int)BlockIo, MediaDesc, 0, 0x200u, gDataPtr + 1920); /*0x3481*/
  if ( Status < 0 ) /*0x3488*/
  {
    DebugLogPrint(-1, (int)BlockIo, "\nRead first sector failed\n"); /*0x3492*/
    return Status; /*0x3499*/
  }
  for ( i = 0; i < 0x200; ++i ) /*0x34aa*/
  {
    if ( *(_BYTE *)(i + gDataPtr + 1920) ) /*0x34ac*/
    {
      DebugLogPrint(-1, (int)BlockIo, "\nFirst sector not blank\n"); /*0x3713*/
      return -2147483634; /*0x3713*/
    }
  }
  ReadBlocks((int)BlockIo, MediaDesc, 1024, 0x200u, gDataPtr + 1920); /*0x34c9*/
  if ( *(_WORD *)(gDataPtr + 1976) != 0xEF53 /*0x3511*/
    || *(_DWORD *)(gDataPtr + 1944) >= 4u
    || *(_DWORD *)(gDataPtr + 1940) >= 2u
    || *(_DWORD *)(gDataPtr + 1932) >= *(_DWORD *)(gDataPtr + 1924)
    || *(_DWORD *)(gDataPtr + 1936) >= *(_DWORD *)(gDataPtr + 1920) )
  {
    DebugLogPrint(-1, (int)BlockIo, "\nIsExt failed\n"); /*0x3709*/
    return -2147483634; /*0x3718*/
  }
  Superblock = gDataPtr + 1920; /*0x3517*/
  byte_4BC1 = 0; /*0x351b*/
  Status = ReadExt4BlockBitmap(BlockIo, MediaDesc, gDataPtr + 1920); /*0x3529*/
  if ( Status < 0 ) /*0x352f*/
  {
    DebugLogPrint(-1, (int)BlockIo, "\nRead EXT root failed\n"); /*0x3536*/
    return Status; /*0x3536*/
  }
  ReadElToritoBoot(Superblock, (char *)&NumEntries); /*0x3544*/
  if ( !NumEntries ) /*0x3552*/
    return -2147483634; /*0x3554*/
  BlockSize = *(unsigned __int16 *)(gDataPtr + 2008); /*0x356d*/
  BlockGroupSz = 1024 << *(_DWORD *)(gDataPtr + 1944); /*0x357a*/
  BlockSize_1 = BlockSize; /*0x3582*/
  BaseAddr = MultU64x32((unsigned int)BlockGroupSz); /*0x3587*/
  BaseAddr_1 = BaseAddr; /*0x358f*/
  EntryIndex = 0; /*0x3593*/
  AddrHi = HIDWORD(BaseAddr); /*0x3595*/
  while ( 1 ) /*0x35b2*/
  {
    AdjustedBlock = *(_DWORD *)dword_4C60[EntryIndex] - 1; /*0x35b2*/
    TableOffset = 0; /*0x35b3*/
    AdjustedBlock_1 = *(_DWORD *)(gDataPtr + 1960); /*0x35b5*/
    if ( AdjustedBlock > AdjustedBlock_1 ) /*0x35bb*/
    {
      TableSlot = AdjustedBlock / AdjustedBlock_1; /*0x35c5*/
      AdjustedBlock %= AdjustedBlock_1; /*0x35c7*/
      TableOffset = 32 * TableSlot; /*0x35c9*/
    }
    if ( ReadBlocks( /*0x35ed*/
           (int)BlockIo,
           MediaDesc,
           __PAIR64__(AddrHi, BaseAddr_1) + (unsigned int)TableOffset,
           0x20u,
           (unsigned int)EntryBuf) < 0 )
    {
      DebugLogPrint(-1, (int)BlockIo, "\nRead BGBT error\n"); /*0x3702*/
      return -2147483634; /*0x3702*/
    }
    ::BgbtVal = BgbtVal; /*0x35f7*/
    BlockAddr = MultU64x32(AdjustedBlock); /*0x3606*/
    BaseAddr_2 = MultU64x32((unsigned int)BlockGroupSz) + BlockAddr; /*0x3638*/
    AddrHi = HIDWORD(BaseAddr_2); /*0x3638*/
    BaseAddr_1 = BaseAddr_2; /*0x3638*/
    if ( ReadBlocks((int)BlockIo, MediaDesc, __SPAIR64__(AddrHi, BaseAddr_1), 0x80u, gDataPtr + 2560) >= 0 ) /*0x3652*/
    {
      FileSizeHigh = LShiftU64(*(unsigned int *)(gDataPtr + 2668)); /*0x3663*/
      FileSizeLow = *(_DWORD *)(gDataPtr + 2564); /*0x3670*/
      ReadSize = FileSizeHigh + FileSizeLow; /*0x3676*/
      TotalFileSize = FileSizeHigh + FileSizeLow; /*0x367a*/
      DebugLogPrint(-1, (int)BlockIo, "\nSize of file found is %lx\n", (_DWORD)FileSizeHigh + FileSizeLow); /*0x368b*/
      if ( *FileSize >= TotalFileSize ) /*0x3699*/
        break; /*0x3699*/
    }
    if ( ++EntryIndex >= NumEntries ) /*0x36a0*/
      return -2147483634; /*0x36a0*/
  }
  DirResult = ReadExt4DirInode( /*0x36cc*/
                BlockIo,
                MediaDesc,
                gDataPtr + 1920,
                (_WORD *)(gDataPtr + 2560),
                ZeroCheck,
                (unsigned int *)&ReadSize);
  DirResult_1 = DirResult; /*0x36d1*/
  if ( DirResult < 0 ) /*0x36d8*/
  {
    DebugLogPrint(-1, (int)BlockIo, "\nRead of file returned %r\n", DirResult); /*0x36f1*/
    return DirResult_1; /*0x36f9*/
  }
  else
  {
    *FileSize = ReadSize; /*0x36e2*/
    return 0; /*0x36e4*/
  }
}


// Function: ReadIsoRoot @ 0x3728 (0xa8 bytes)
// Index: 62/77

int __cdecl ReadIsoRoot(int *i, int MftRef, unsigned int *FileSize, unsigned int ZeroCheck)
{
  int result; // eax
  int v5; // ebx
  bool v6; // zf

  *(_DWORD *)(MftRef + 21) = 0; /*0x3740*/
  *(_DWORD *)(MftRef + 25) = 0; /*0x3743*/
  result = ReadExt4FileData(i, MftRef, FileSize, ZeroCheck); /*0x3746*/
  if ( result < 0 ) /*0x374f*/
  {
    result = ReadBlocks((int)i, MftRef, 0, 0x200u, gDataPtr); /*0x3763*/
    if ( result >= 0 ) /*0x376d*/
    {
      if ( *(_WORD *)(gDataPtr + 510) == 0xAA55 ) /*0x3780*/
      {
        gPartIdx = 0; /*0x3782*/
        gLbaOffset = 0; /*0x3788*/
        ExtPartLbaOffset = 0; /*0x378e*/
        gExtendFlag = 1; /*0x3794*/
        do /*0x37c3*/
        {
          v5 = ParsePartitionEntry((int)i, MftRef); /*0x37a5*/
          v6 = v5 == 0; /*0x37a7*/
          if ( v5 >= 0 ) /*0x37a9*/
          {
            result = ReadExt4FileData(i, MftRef, FileSize, ZeroCheck); /*0x37b6*/
            if ( result >= 0 ) /*0x37bf*/
              return result; /*0x37bf*/
            v6 = v5 == 0; /*0x37c1*/
          }
        }
        while ( v6 ); /*0x37c3*/
      }
      return -2147483634; /*0x37c5*/
    }
  }
  return result; /*0x37ca*/
}


// Function: ReadIsoDir @ 0x37d0 (0x9c bytes)
// Index: 63/77

char __fastcall ReadIsoDir(int i, int n4096, char *dst, _DWORD *p_RecoveryImageConfig)
{
  int n4096_1; // ebp
  unsigned __int16 v6; // di
  unsigned __int8 v7; // bl
  char *v8; // ecx
  int n4096_3; // ebp
  int n4096_4; // [esp-8h] [ebp-A0h]
  int n4096_2; // [esp+10h] [ebp-88h]
  char v13[128]; // [esp+18h] [ebp-80h] BYREF

  n4096_1 = n4096; /*0x37d9*/
  n4096_2 = n4096; /*0x37de*/
  while ( 1 ) /*0x37e2*/
  {
    v6 = *(_WORD *)(i + 4); /*0x37e2*/
    if ( !v6 ) /*0x37ed*/
      return 0; /*0x385e*/
    LOBYTE(n4096) = *(_BYTE *)(i + 6); /*0x37ef*/
    v7 = 0; /*0x37f2*/
    if ( (_BYTE)n4096 ) /*0x37f6*/
    {
      v8 = v13; /*0x37f8*/
      v7 = *(_BYTE *)(i + 6); /*0x37fc*/
      n4096_3 = (unsigned __int8)n4096; /*0x3805*/
      do /*0x3811*/
      {
        *v8 = v8[i - (_DWORD)v13 + 8]; /*0x380b*/
        ++v8; /*0x380d*/
        --n4096_3; /*0x380e*/
      }
      while ( n4096_3 ); /*0x3811*/
      n4096_1 = n4096_2; /*0x3817*/
    }
    v13[v7] = 0; /*0x381e*/
    if ( *dst ) /*0x382a*/
    {
      n4096_4 = (unsigned __int8)n4096; /*0x3837*/
      LOBYTE(n4096) = 0; /*0x3838*/
      if ( MatchNameWildcard(v13, n4096, n4096_4, dst) >= 0 ) /*0x3843*/
        break; /*0x3843*/
    }
    i += v6; /*0x3848*/
    n4096_1 -= v6; /*0x384a*/
    n4096_2 = n4096_1; /*0x384c*/
    if ( !n4096_1 ) /*0x3850*/
      return 0; /*0x3850*/
  }
  *p_RecoveryImageConfig = i; /*0x3866*/
  return 1; /*0x3854*/
}


// Function: ReadElToritoBoot @ 0x386c (0x82 bytes)
// Index: 64/77

char __cdecl ReadElToritoBoot(int Superblock, char *p_NumEntries)
{
  int v2; // ecx
  char *gTmpBufPtr; // ebx
  char *p_NumEntries_1; // esi
  int n4096; // edi
  int RecoveryImageConfig; // eax
  int v7; // eax
  int NumEntries; // ecx
  char dst[256]; // [esp+Ch] [ebp-108h] BYREF
  int v11; // [esp+10Ch] [ebp-8h] BYREF
  int p_RecoveryImageConfig; // [esp+110h] [ebp-4h] BYREF

  gTmpBufPtr = gTmpBufPtr; /*0x3876*/
  p_NumEntries_1 = p_NumEntries; /*0x3880*/
  n4096 = n4096; /*0x3886*/
  p_RecoveryImageConfig = 0; /*0x388d*/
  *(_DWORD *)p_NumEntries = 0; /*0x3890*/
  RecoveryImageConfig = GetRecoveryImageConfig(v2, &p_NumEntries, &v11, 0); /*0x3896*/
  if ( RecoveryImageConfig >= 0 ) /*0x389f*/
  {
    v7 = StrLen(p_NumEntries); /*0x38a4*/
    CopyMemEx((unsigned int)dst, p_NumEntries, v7 + 1); /*0x38b5*/
    LOBYTE(RecoveryImageConfig) = ReadIsoDir((int)gTmpBufPtr, n4096, dst, &p_RecoveryImageConfig); /*0x38c9*/
    if ( (_BYTE)RecoveryImageConfig ) /*0x38d3*/
    {
      NumEntries = *(_DWORD *)p_NumEntries_1; /*0x38d5*/
      RecoveryImageConfig = p_RecoveryImageConfig; /*0x38d7*/
      *(_DWORD *)p_NumEntries_1 = 1; /*0x38da*/
      dword_4C60[NumEntries] = RecoveryImageConfig; /*0x38e0*/
    }
  }
  return RecoveryImageConfig; /*0x38e7*/
}


// Function: ReadElToritoCatalog @ 0x38ee (0xcf bytes)
// Index: 65/77

int __fastcall ReadElToritoCatalog(
        int buf,
        int BootSector,
        unsigned int i,
        unsigned int n4,
        unsigned int dst,
        unsigned int dsta)
{
  unsigned int i_1; // edi
  __int64 v9; // rax
  int Blocks; // eax
  int Blocks_1; // esi
  int result; // eax
  unsigned int n4_2; // ebx
  unsigned int n4_3; // ebp
  int v15; // eax
  __int64 v16; // rax
  unsigned int n4_1; // [esp-8h] [ebp-1Ch]
  unsigned int dsta_1; // [esp-4h] [ebp-18h]
  unsigned int dst_1; // [esp-4h] [ebp-18h]

  i_1 = i; /*0x38fc*/
  if ( (_BYTE)dst ) /*0x3904*/
  {
    dsta_1 = dsta; /*0x3906*/
    n4_1 = n4; /*0x3910*/
    v9 = MultU64x32(i - 2); /*0x3917*/
    Blocks = ReadBlocks(buf, BootSector, *(_QWORD *)(BootSector + 45) + v9, n4_1, dsta_1); /*0x392b*/
    Blocks_1 = Blocks; /*0x3930*/
    if ( Blocks < 0 ) /*0x3937*/
      DebugLogPrint(-1, buf, "\nRead status is %r\n", Blocks); /*0x3942*/
    return Blocks_1; /*0x394a*/
  }
  else
  {
    n4_2 = n4; /*0x3956*/
    dst = dsta; /*0x395a*/
    while ( 1 ) /*0x3969*/
    {
      n4_3 = n4_2; /*0x3969*/
      v15 = WalkClusterChain(5, i_1, (char **)&i, 1); /*0x396b*/
      if ( n4_2 > v15 * *(_DWORD *)(BootSector + 53) ) /*0x397c*/
        n4_3 = v15 * *(_DWORD *)(BootSector + 53); /*0x397e*/
      dst_1 = dst; /*0x3980*/
      v16 = MultU64x32(i_1 - 2); /*0x398b*/
      result = ReadBlocks(buf, BootSector, *(_QWORD *)(BootSector + 45) + v16, n4_3, dst_1); /*0x39a1*/
      if ( result < 0 ) /*0x39ab*/
        break; /*0x39ab*/
      i_1 = i; /*0x39ad*/
      if ( !i ) /*0x39b3*/
        break; /*0x39b3*/
      dst += n4_3; /*0x39b5*/
      n4_2 -= n4_3; /*0x39b9*/
    }
  }
  return result; /*0x394c*/
}


// Function: ReadIso9660_2 @ 0x39bd (0x172 bytes)
// Index: 66/77

int __fastcall ReadIso9660_2(int buf, int BootSector, int a3)
{
  unsigned int v4; // ebx
  int v5; // esi
  unsigned int n0x20000; // edi
  __int64 v7; // rax
  bool v8; // cf
  int result; // eax
  unsigned int n4; // esi
  int gAllocBufPtr; // eax
  int v12; // ebx
  char *gTmpBufPtr; // ecx
  char *p_i; // [esp+14h] [ebp-Ch] BYREF
  char *bufa; // [esp+18h] [ebp-8h] BYREF

  p_i = 0; /*0x39d1*/
  v4 = 1 << *(_BYTE *)(a3 + 108); /*0x39db*/
  v5 = (v4 << *(_BYTE *)(a3 + 109)) / v4; /*0x39eb*/
  n0x20000 = v4 * *(_DWORD *)(a3 + 84); /*0x39ed*/
  *(_QWORD *)(BootSector + 29) = MultU64x32(*(unsigned int *)(a3 + 80)); /*0x3a04*/
  *(_QWORD *)(BootSector + 45) = MultU64x32(*(unsigned int *)(a3 + 88)); /*0x3a1e*/
  v7 = MultU64x32((unsigned int)(v5 * (*(_DWORD *)(a3 + 96) - 2))); /*0x3a34*/
  v8 = __CFADD__(*(_DWORD *)(BootSector + 45), (_DWORD)v7); /*0x3a3e*/
  *(_DWORD *)(BootSector + 37) = *(_DWORD *)(BootSector + 45) + v7; /*0x3a41*/
  *(_DWORD *)(BootSector + 41) = *(_DWORD *)(BootSector + 49) + v8 + HIDWORD(v7); /*0x3a4b*/
  *(_DWORD *)(BootSector + 53) = v4 << *(_BYTE *)(a3 + 109); /*0x3a57*/
  *(_BYTE *)(BootSector + 12) = 5; /*0x3a5a*/
  result = InitCache(buf, BootSector, n0x20000); /*0x3a5e*/
  if ( result >= 0 ) /*0x3a68*/
  {
    n4 = WalkClusterChain(5, *(_DWORD *)(a3 + 96), &p_i, 0) * *(_DWORD *)(BootSector + 53); /*0x3a86*/
    Index = n4 >> 5; /*0x3a9a*/
    gAllocBufPtr = gAllocBufPtr; /*0x3aaa*/
    if ( gAllocBufPtr >= ((n4 >> 12) + ((n4 & 0xFFF) != 0)) << 12 ) /*0x3ab6*/
    {
      gTmpBufPtr = gTmpBufPtr; /*0x3af7*/
    }
    else
    {
      v12 = (*(int (__cdecl **)(int, int, unsigned int, char **))(*(_DWORD *)buf + 72))( /*0x3ac7*/
              buf,
              4,
              (n4 >> 12) + ((n4 & 0xFFF) != 0),
              &bufa);
      if ( v12 < 0 ) /*0x3ace*/
      {
        DebugLogPrint(-1, buf, "\nAllocate for root pages failed\n"); /*0x3ad8*/
        return v12; /*0x3ae2*/
      }
      gTmpBufPtr = bufa; /*0x3ae4*/
      gAllocBufPtr = ((n4 >> 12) + ((n4 & 0xFFF) != 0)) << 12; /*0x3ae8*/
      gTmpBufPtr = bufa; /*0x3aea*/
      gAllocBufPtr = gAllocBufPtr; /*0x3af0*/
    }
    ZeroMemEx(gAllocBufPtr, gTmpBufPtr, gAllocBufPtr, 0); /*0x3b01*/
    return ReadElToritoCatalog(buf, BootSector, *(_DWORD *)(a3 + 96), n4, 0, (unsigned int)gTmpBufPtr); /*0x3b1f*/
  }
  return result; /*0x3b27*/
}


// Function: SearchVolume @ 0x3b2f (0x165 bytes)
// Index: 67/77

int __fastcall SearchVolume(int buf, int BootSector, unsigned int *a3, unsigned int i)
{
  int v4; // edi
  int Blocks; // ebx
  unsigned __int8 n9; // cl
  unsigned int dst_1; // ebp
  int v11; // ecx
  unsigned int n4; // ebx
  int v13; // [esp-4h] [ebp-20h]
  unsigned int dst; // [esp+14h] [ebp-8h] BYREF
  int BootSectora; // [esp+18h] [ebp-4h]

  v4 = 0; /*0x3b40*/
  BootSectora = BootSector; /*0x3b4e*/
  Blocks = ReadBlocks(buf, BootSector, 0, 0x200u, gDataPtr + 512); /*0x3b57*/
  if ( Blocks < 0 ) /*0x3b5e*/
  {
    DebugLogPrint(-1, buf, "\nRead boot sector failed\n"); /*0x3b68*/
    return Blocks; /*0x3b72*/
  }
  n9 = *(_BYTE *)(gDataPtr + 620); /*0x3b81*/
  if ( n9 < 9u /*0x3bcc*/
    || n9 > 0xCu
    || *(_BYTE *)(gDataPtr + 523)
    || *(_BYTE *)(gDataPtr + 515) != 69
    || *(_BYTE *)(gDataPtr + 516) != 88
    || *(_BYTE *)(gDataPtr + 517) != 70
    || *(_BYTE *)(gDataPtr + 518) != 65
    || *(_BYTE *)(gDataPtr + 519) != 84 )
  {
    return -2147483634; /*0x3bcc*/
  }
  Blocks = ReadIso9660_2(buf, BootSector, gDataPtr + 512); /*0x3bdc*/
  if ( Blocks < 0 ) /*0x3be1*/
  {
    DebugLogPrint(-1, buf, "\nRead root failed\n"); /*0x3be8*/
    return Blocks; /*0x3be8*/
  }
  ValidateFwCapsule(v13, (char *)&dst); /*0x3bf6*/
  dst_1 = dst; /*0x3bfb*/
  if ( !dst ) /*0x3c04*/
    return -2147483634; /*0x3c89*/
  DebugLogPrint(-1, buf, "\nFound a recovery file\n"); /*0x3c0e*/
  while ( 1 ) /*0x3c1a*/
  {
    v11 = dword_4C20[v4]; /*0x3c1a*/
    n4 = *(_DWORD *)(v11 + 24); /*0x3c25*/
    if ( *a3 >= n4 ) /*0x3c2a*/
      break; /*0x3c2a*/
    DebugLogPrint(-1, buf, "\nFile size is wrong, %x\n", *(_DWORD *)(v11 + 24)); /*0x3c35*/
LABEL_20:
    if ( ++v4 >= dst_1 ) /*0x3c7b*/
      return -2147483634; /*0x3c7b*/
  }
  LOBYTE(dst) = (*(_BYTE *)(v11 + 1) & 2) != 0; /*0x3c4e*/
  if ( ReadElToritoCatalog(buf, BootSectora, *(_DWORD *)(v11 + 20), n4, dst, i) < 0 ) /*0x3c66*/
  {
    DebugLogPrint(-1, buf, "\nError reading recovery file\n"); /*0x3c70*/
    goto LABEL_20; /*0x3c70*/
  }
  *a3 = n4; /*0x3c8e*/
  return 0; /*0x3c82*/
}


// Function: ReadBgbt @ 0x3c94 (0xc3 bytes)
// Index: 68/77

int __cdecl ReadBgbt(int i, int BootSector, unsigned int *a3, unsigned int i_1)
{
  int result; // eax
  int Blocks; // ebx
  int v6; // ebx
  bool v7; // zf

  *(_DWORD *)(BootSector + 21) = 0; /*0x3cb0*/
  *(_DWORD *)(BootSector + 25) = 0; /*0x3cb3*/
  result = SearchVolume(i, BootSector, a3, i_1); /*0x3cb6*/
  if ( result < 0 ) /*0x3cbf*/
  {
    Blocks = ReadBlocks(i, BootSector, 0, 0x200u, gDataPtr); /*0x3cdb*/
    if ( Blocks >= 0 ) /*0x3ce2*/
    {
      if ( *(_WORD *)(gDataPtr + 510) == 0xAA55 ) /*0x3d09*/
      {
        gExtendFlag = 1; /*0x3d0d*/
        gPartIdx = 0; /*0x3d14*/
        gLbaOffset = 0; /*0x3d19*/
        ExtPartLbaOffset = 0; /*0x3d1e*/
        do /*0x3d49*/
        {
          v6 = ParsePartitionEntry(i, BootSector); /*0x3d2c*/
          v7 = v6 == 0; /*0x3d2e*/
          if ( v6 >= 0 ) /*0x3d30*/
          {
            result = SearchVolume(i, BootSector, a3, i_1); /*0x3d3c*/
            if ( result >= 0 ) /*0x3d45*/
              return result; /*0x3d45*/
            v7 = v6 == 0; /*0x3d47*/
          }
        }
        while ( v7 ); /*0x3d49*/
      }
      return -2147483634; /*0x3d4b*/
    }
    else
    {
      DebugLogPrint(-1, i, "\nRead MBR failed\n"); /*0x3cec*/
      return Blocks; /*0x3cf4*/
    }
  }
  return result; /*0x3d50*/
}


// Function: GetRecoveryFileData @ 0x3d57 (0xfd bytes)
// Index: 69/77

char __usercall GetRecoveryFileData@<al>(int i@<edx>, unsigned int Index, char *dst, _DWORD *p_RecoveryImageConfig)
{
  int v4; // edi
  int i_1; // ebp
  unsigned __int8 MaxLen_1; // bh
  _WORD *j; // esi
  char v8; // al
  int v9; // eax
  _BYTE *CaseSensitive_2; // ebp
  int CaseSensitive; // edx
  unsigned __int8 n15; // bl
  bool v13; // zf
  unsigned __int8 MaxLen_2; // [esp+12h] [ebp-8Eh]
  unsigned __int8 MaxLen; // [esp+13h] [ebp-8Dh]
  int CaseSensitive_1; // [esp+18h] [ebp-88h]
  _WORD *v19; // [esp+1Ch] [ebp-84h]
  char v20[128]; // [esp+20h] [ebp-80h] BYREF

  v4 = 0; /*0x3d61*/
  i_1 = i; /*0x3d63*/
  if ( !Index ) /*0x3d70*/
    return 0; /*0x3e42*/
  MaxLen_1 = MaxLen; /*0x3d76*/
  for ( j = (_WORD *)(i + 38); ; j += 16 ) /*0x3d7a*/
  {
    v8 = *((_BYTE *)j - 38); /*0x3d7d*/
    if ( !v8 ) /*0x3d82*/
      return 0; /*0x3d82*/
    if ( v8 == -123 ) /*0x3d88*/
      break; /*0x3d88*/
LABEL_17:
    if ( ++v4 >= Index ) /*0x3e30*/
      return 0; /*0x3e30*/
  }
  v9 = v4 + 1; /*0x3da0*/
  if ( *((_BYTE *)j - 6) == 0xC0 ) /*0x3da3*/
  {
    MaxLen_1 = 0; /*0x3da8*/
    MaxLen = *((_BYTE *)j - 3); /*0x3daa*/
    MaxLen_2 = MaxLen; /*0x3dae*/
    v9 = v4 + 2; /*0x3db2*/
    *j = *(j - 17); /*0x3db5*/
    v19 = j - 3; /*0x3db8*/
  }
  CaseSensitive_2 = (_BYTE *)(32 * v9 + i_1); /*0x3dbf*/
LABEL_8:
  if ( *CaseSensitive_2 != 0xC1 ) /*0x3dc5*/
  {
    i_1 = i; /*0x3e21*/
    goto LABEL_17; /*0x3e21*/
  }
  CaseSensitive = (int)CaseSensitive_2; /*0x3dc7*/
  CaseSensitive_2 += 32; /*0x3dc9*/
  CaseSensitive_1 = CaseSensitive; /*0x3dcc*/
  n15 = 0; /*0x3dd0*/
  while ( 1 ) /*0x3dd2*/
  {
    v13 = MaxLen_2-- == 1; /*0x3dd2*/
    v20[MaxLen_1] = *(_BYTE *)(CaseSensitive + 2 * n15 + 2); /*0x3de1*/
    if ( !v13 ) /*0x3de5*/
      goto LABEL_14; /*0x3de5*/
    n15 = 15; /*0x3dee*/
    v20[MaxLen_1 + 1] = 0; /*0x3df0*/
    if ( !*dst ) /*0x3df5*/
      goto LABEL_14; /*0x3df8*/
    LOBYTE(CaseSensitive) = 0; /*0x3e05*/
    if ( MatchNameWildcard(v20, CaseSensitive, MaxLen, dst) >= 0 ) /*0x3e10*/
      break; /*0x3e10*/
    CaseSensitive = CaseSensitive_1; /*0x3e12*/
LABEL_14:
    ++n15; /*0x3e16*/
    ++MaxLen_1; /*0x3e18*/
    if ( n15 >= 0xFu ) /*0x3e1d*/
      goto LABEL_8; /*0x3e1d*/
  }
  *p_RecoveryImageConfig = v19; /*0x3e4e*/
  return 1; /*0x3e38*/
}


// Function: ValidateFwCapsule @ 0x3e54 (0x81 bytes)
// Index: 70/77

char __cdecl ValidateFwCapsule(int a1, char *p_dst)
{
  int v2; // ecx
  unsigned int Index; // ebx
  char *p_dst_1; // esi
  char *gTmpBufPtr; // edi
  int RecoveryImageConfig; // eax
  int v7; // eax
  int dst_1; // ecx
  char dst[256]; // [esp+Ch] [ebp-108h] BYREF
  int v11; // [esp+10Ch] [ebp-8h] BYREF
  int p_RecoveryImageConfig; // [esp+110h] [ebp-4h] BYREF

  Index = Index; /*0x3e5e*/
  p_dst_1 = p_dst; /*0x3e68*/
  gTmpBufPtr = gTmpBufPtr; /*0x3e6e*/
  p_RecoveryImageConfig = 0; /*0x3e75*/
  *(_DWORD *)p_dst = 0; /*0x3e78*/
  RecoveryImageConfig = GetRecoveryImageConfig(v2, &p_dst, &v11, 0); /*0x3e7e*/
  if ( RecoveryImageConfig >= 0 ) /*0x3e87*/
  {
    v7 = StrLen(p_dst); /*0x3e8c*/
    CopyMemEx((unsigned int)dst, p_dst, v7 + 1); /*0x3e9d*/
    LOBYTE(RecoveryImageConfig) = GetRecoveryFileData((int)gTmpBufPtr, Index, dst, &p_RecoveryImageConfig); /*0x3eb0*/
    if ( (_BYTE)RecoveryImageConfig ) /*0x3eba*/
    {
      dst_1 = *(_DWORD *)p_dst_1; /*0x3ebc*/
      RecoveryImageConfig = p_RecoveryImageConfig; /*0x3ebe*/
      *(_DWORD *)p_dst_1 = 1; /*0x3ec1*/
      dword_4C20[dst_1] = RecoveryImageConfig; /*0x3ec7*/
    }
  }
  return RecoveryImageConfig; /*0x3ece*/
}


// Function: ValidateRecoveryParams @ 0x3ed5 (0x11b bytes)
// Index: 71/77

int __fastcall ValidateRecoveryParams(int a1, _DWORD *a2, _DWORD *a3, _BYTE *a4)
{
  int result; // eax
  int v7; // ebp
  double v8; // [esp-8h] [ebp-30h]
  int v9; // [esp+0h] [ebp-28h]
  int (__cdecl **v10)(_DWORD, const __int16 *, _DWORD *, _DWORD, int *, char *); // [esp+10h] [ebp-18h] BYREF
  int n29; // [esp+14h] [ebp-14h] BYREF
  _DWORD v12[4]; // [esp+18h] [ebp-10h] BYREF

  v10 = 0; /*0x3ee4*/
  v12[0] = -1757269547; /*0x3ee8*/
  v12[1] = 1154608459; /*0x3ef2*/
  v12[2] = 1372483720; /*0x3efa*/
  v12[3] = 1749926236; /*0x3f02*/
  if ( !a2 && !a3 ) /*0x3f10*/
    return -2147483645; /*0x3f17*/
  if ( a4 ) /*0x3f22*/
    *a4 = 1; /*0x3f24*/
  if ( a3 ) /*0x3f29*/
  {
    DebugPrint(64, (int)"FW Capsule Info\nDefault Size %X\n", *a3); /*0x3f38*/
    if ( *a3 < 0x1004000u ) /*0x3f47*/
      *a3 = 16793600; /*0x3f49*/
    if ( a2 ) /*0x3f4d*/
    {
      HIDWORD(v8) = *a3; /*0x3f53*/
      LODWORD(v8) = *a2; /*0x3f55*/
      DebugPrint(64, (int)"Default Name %a, Size %X\n", v8, v9); /*0x3f5e*/
      result = (*(int (__cdecl **)(int, void *, _DWORD, _DWORD, int (__cdecl ***)(_DWORD, const __int16 *, _DWORD *, _DWORD, int *, char *)))(*(_DWORD *)a1 + 32))( /*0x3f72*/
                 a1,
                 &unk_4B00,
                 0,
                 0,
                 &v10);
      if ( result < 0 ) /*0x3f7a*/
        return result; /*0x3f7a*/
      n29 = 29; /*0x3f85*/
      v7 = (*v10)(v10, L"AmiFlashUpd", v12, 0, &n29, &byte_4C00); /*0x3fa0*/
      if ( v7 >= 0 ) /*0x3fa7*/
      {
        if ( byte_4C00 == 1 ) /*0x3fb0*/
        {
          if ( byte_4C05 ) /*0x3fb9*/
            *a2 = &byte_4C05; /*0x3fbb*/
        }
        *a3 = dword_4C15; /*0x3fc6*/
        (*(void (__cdecl **)(int, int))(*(_DWORD *)a1 + 44))(a1, 18); /*0x3fcd*/
      }
      DebugPrint(64, (int)"ReFlash variable %r\nImage Name %a, Size %X\n", v7, *a2, *a3); /*0x3fde*/
    }
  }
  return 0; /*0x3fe8*/
}


// Function: GetImageHandle @ 0x3ff0 (0x32 bytes)
// Index: 72/77

int GetImageHandle()
{
  int v0; // esi
  _BYTE v2[2]; // [esp+4h] [ebp-8h] BYREF
  int v3; // [esp+6h] [ebp-6h]

  ReservedFunc2(v2); /*0x3ff9*/
  v0 = *(_DWORD *)(v3 - 4); /*0x4001*/
  if ( !v0 ) /*0x4006*/
    DebugAssert( /*0x4015*/
      (int)"e:\\hs\\MdePkg\\Library\\PeiServicesTablePointerLibIdt\\PeiServicesTablePointer.c",
      48,
      (int)"PeiServices != ((void *) 0)");
  return v0; /*0x401d*/
}


// Function: GetDebugPrintLevel @ 0x4022 (0x4f bytes)
// Index: 73/77

int GetDebugPrintLevel()
{
  unsigned __int8 v0; // al
  char n3; // al
  char n3_1; // cl

  v0 = __inbyte(0x70u); /*0x4028*/
  __outbyte(0x70u, v0 & 0x80 | 0x4A); /*0x402d*/
  n3 = __inbyte(0x71u); /*0x4034*/
  n3_1 = n3; /*0x4035*/
  if ( (unsigned __int8)n3 <= 3u ) /*0x403a*/
  {
LABEL_4:
    if ( !n3_1 ) /*0x4055*/
      return 0; /*0x4055*/
    goto LABEL_5; /*0x4055*/
  }
  n3_1 = n3; /*0x403c*/
  if ( !n3 ) /*0x4044*/
  {
    n3_1 = MEMORY[0xFDAF0490] & 2 | 1; /*0x4050*/
    goto LABEL_4; /*0x4050*/
  }
LABEL_5:
  if ( n3_1 != -1 )
    return n3_1 != 1 ? -2147483578 : -2147483644;
  return 0; /*0x406d*/
}


// Function: ReservedFunc2 @ 0x4071 (0x23 bytes)
// Index: 74/77

void *__thiscall ReservedFunc2(void *this)
{
  void *this_1; // eax

  if ( !this ) /*0x4077*/
    DebugAssert((int)"e:\\hs\\MdePkg\\Library\\BaseLib\\X86ReadIdtr.c", 37, (int)"Idtr != ((void *) 0)"); /*0x4086*/
  this_1 = this; /*0x408c*/
  __sidt(this); /*0x408f*/
  return this_1; /*0x4093*/
}


// Function: ReservedFunc1 @ 0x40a0 (0xa bytes)
// Index: 75/77

// (too small: 0xa bytes)


// Function: ZeroMemEx @ 0x40aa (0x48 bytes)
// Index: 76/77

char *__usercall ZeroMemEx@<eax>(int value@<eax>, char *buf, unsigned int n4, char a4)
{
  unsigned int n4_1; // ecx
  char *buf_1; // edi
  __int16 value_1; // bx
  int value_2; // eax
  int v8; // edx
  char n4_2; // dl
  unsigned int count; // ecx

  n4_1 = n4; /*0x40aa*/
  LOBYTE(value) = a4; /*0x40ae*/
  buf_1 = buf; /*0x40b3*/
  BYTE1(value) = a4; /*0x40bc*/
  value_1 = value; /*0x40be*/
  value_2 = value << 16; /*0x40c1*/
  LOWORD(value_2) = value_1; /*0x40c4*/
  if ( n4 >= 4 ) /*0x40ca*/
  {
    v8 = (unsigned __int8)buf & 3; /*0x40ce*/
    if ( ((unsigned __int8)buf & 3) != 0 ) /*0x40d1*/
    {
      memset(buf, value_1, 4 - v8); /*0x40dc*/
      buf_1 = &buf[4 - v8]; /*0x40dc*/
      n4_1 = n4 - (4 - v8); /*0x40de*/
    }
    n4_2 = n4_1; /*0x40e0*/
    count = n4_1 >> 2; /*0x40e2*/
    memset32(buf_1, value_2, count); /*0x40e5*/
    buf_1 += 4 * count; /*0x40e5*/
    n4_1 = n4_2 & 3; /*0x40ea*/
  }
  memset(buf_1, value_1, n4_1); /*0x40ec*/
  return buf; /*0x40f0*/
}


// Function: CopyMemEx @ 0x4100 (0x91 bytes)
// Index: 77/77

unsigned int __cdecl CopyMemEx(unsigned int dst, char *src, unsigned int n4)
{
  char *src_1; // esi
  unsigned int dst_1; // edi
  unsigned int n4_1; // ecx
  char v10; // dl
  char *n4_2; // eax
  unsigned int count; // eax
  int count_1; // ebx
  char n4_3; // al
  unsigned int v15; // ecx
  int n4_4; // eax

  __asm { pushfw } /*0x4106*/
  src_1 = src; /*0x410b*/
  dst_1 = dst; /*0x410e*/
  n4_1 = n4; /*0x4111*/
  v10 = 0; /*0x4114*/
  n4_2 = &src[-dst]; /*0x4118*/
  if ( (unsigned int)src < dst ) /*0x411a*/
  {
    n4_2 = (char *)(dst - (_DWORD)src); /*0x411f*/
    if ( (unsigned int)&src[n4] >= dst ) /*0x4123*/
    {
      src_1 = &src[n4]; /*0x4125*/
      dst_1 = n4 + dst; /*0x4127*/
      v10 = 1; /*0x412a*/
    }
  }
  if ( n4 < 4 || (unsigned int)n4_2 < 4 ) /*0x4135*/
    goto LABEL_19; /*0x4135*/
  count = (unsigned __int8)src_1 & 3; /*0x413b*/
  count_1 = dst_1 & 3; /*0x413e*/
  if ( v10 ) /*0x4143*/
  {
    --src_1; /*0x4145*/
    --dst_1; /*0x4146*/
  }
  if ( count == count_1 && count ) /*0x414d*/
  {
    if ( !v10 ) /*0x4151*/
      count = 4 - count; /*0x4155*/
    qmemcpy((void *)dst_1, src_1, count); /*0x415b*/
    src_1 += count; /*0x415b*/
    dst_1 += count; /*0x415b*/
    n4_1 = n4 - count; /*0x415d*/
  }
  if ( v10 ) /*0x4161*/
  {
    src_1 -= 3; /*0x4163*/
    dst_1 -= 3; /*0x4166*/
  }
  n4_3 = n4_1; /*0x4169*/
  v15 = n4_1 >> 2; /*0x416b*/
  qmemcpy((void *)dst_1, src_1, 4 * v15); /*0x416e*/
  src_1 += 4 * v15; /*0x416e*/
  dst_1 += 4 * v15; /*0x416e*/
  n4_4 = n4_3 & 3; /*0x4170*/
  if ( n4_4 ) /*0x4173*/
  {
    if ( v10 ) /*0x4177*/
    {
      src_1 += 4; /*0x4179*/
      dst_1 += 4; /*0x417c*/
    }
    n4_1 = n4_4; /*0x417f*/
LABEL_19:
    if ( v10 ) /*0x4183*/
    {
      --src_1; /*0x4185*/
      --dst_1; /*0x4186*/
    }
    qmemcpy((void *)dst_1, src_1, n4_1); /*0x4187*/
  }
  __asm { popfw } /*0x4189*/
  return dst; /*0x418c*/
}