⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diskfs.pas

📁 国外著名恢复软件Drive_Rescue 公布的早期源码 版本是1.8 delphi6环境开发的。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  item.cluster:=0;
  item.sector:=0;
  item.name:='Searched';
  item.expanded:=false;
  item.flags:=0;
  item.drive:=self;
  item.children:=TList.create;
  RootDirSearched:=item;
end;


{ Calculate Logical Drive Information from Boot Sector }
function TFATdrive.CalcDriveInfo(pbs: PBootSec; quiet: boolean): boolean;
var
  res: boolean;
  i: longword;
  maxclus: longword;
  value: longword;
  quick_formatted: boolean;
begin
  res:=true;
  try
  with pbootsec32(pbs)^ do
  begin
    { Determine count of sectors occupied by the root directory... }
    RootDirSectors:=((BPB_RootEntCnt * 32) + (BPB_BytesPSec - 1)) div BPB_BytesPSec;
    if (BPB_FATsz16 <> 0) then
      FATsz:=BPB_FATsz16
    else
      FATsz:=BPB_FATsz32;

    { Determine count of sectors occupied by all FATs... }
    FATSectors:=FATsz * BPB_NumFATs;

    { Compute start of data region, the first sector of cluster 2... }
    FirstDataSector := BPB_RsvdSecCnt + (BPB_NumFATs * FATsz) + RootDirSectors;
    if (BPB_TotSec16 <> 0) then
      TotSec:=BPB_TotSec16
    else
      TotSec:=BPB_TotSec32;

    { Determine count of data sectors }
    TotDataSec:=TotSec - FirstDataSector;
    { Determine count of clusters ... }
    CountofClusters:=TotDataSec div BPB_SecPerClus;

    { FAT type detection... }
    if CountofClusters < 4085 then
      FATtype:=FAT12
    else if CountofClusters < 65525 then
      FATtype:=FAT16
    else FATtype:=FAT32;

    { Calculate Bytes per Cluster... }
    BytePerClus:=BPB_BytesPSec * BPB_SecPerClus;
    if (NOT quiet) AND (BytePerClus > 32768) then
      messagebox(0, pchar('bad parameter in boot sector: bytes per sector ('+Inttostr(BytePerClus)+') > 32768 !'),
       'Information', mb_iconinformation + mb_ok);

    if FATtype = FAT32 then
    begin
      if (NOT quiet) AND (BPB_RootClus > countofclusters) then
        messagebox(0, pchar('bad parameter in boot sector: root directory cluster ('+Inttostr(BPB_RootClus)+') > count of clusters !'),
          'Information', mb_iconinformation + mb_ok)
        else if (NOT quiet) AND (BPB_RootClus < 2)  then
          messagebox(0, pchar('bad parameter in boot sector: root directory cluster ('+Inttostr(BPB_RootClus)+') < 2 !'),
            'Information', mb_iconinformation + mb_ok);
      FirstRootDirSecNum:=FirstDataSector + longword(BPB_RootClus-2) * longword(BPB_SecPerClus); // -> sometimes Integer Overflow!!
    end
    else
      FirstRootDirSecNum:=BPB_RsvdSecCnt + (BPB_NumFATs * FATsz);

    if FATType = FAT32 then RootClus:=BPB_RootClus
      else RootClus:=0;

    FFATsec:=0;
    FWorkSec:=0;
    FDataSec:=0;
    useFAT:=1;

    if FATtype = fat32 then name:=bs32_vollab
      else name:=pbootsec(@BootSec)^.bs_vollab;

    // determine the drive's condition (if it is quick-formatted, etc.) ...
    quick_formatted:=TRUE;
    maxclus:=16;
    if maxclus > CountOfClusters+1 then maxclus:=CountOfClusters+1;
    for i:=2 to maxclus do
    begin
      value:=GetFAT(i, 0);
      if value <> RootClus then
      begin
        if (FfatAnalyser.ClusterType(FATtype, value) = clusUsed) then
        begin
          quick_formatted:=FALSE;
          break;
        end;
      end;
    end;
    if quick_formatted then
    begin
      condition:=condition OR drv_cond_quickformatted;
      useFAT:=0;
    end;

  end;
   except
   else
     if NOT quiet then
       messagebox(0, 'Bad parameters for calculating logical drive information from Boot Sector', 'Error', mb_iconinformation + mb_ok);
     res:=false;
  end;
  result:=res;
end;




{-----------------------------------------------------------------------------}
{ ------ FAT manipulaton functions -------------------------------------------}
{-----------------------------------------------------------------------------}


{ Obtain next link number from FAT (12/16/32), FATno: 0=first FAT, 1=2nd FAT, ...}
{ Note: the CountofClusters value is exactly the count of data clusters starting at cluster 2.
  The maximum valid cluster number for the volume is CountofClusters + 1, and the "count of clusters including the two reserved
  clusters" is CountofClusters + 2. }
function TFATdrive.GetFAT(N: longword; FATno: byte): longword;
var
  nextentry, sector, byteoffset: word;
  i: word;
  value: longword;
  FATOffset: longword;
  nFATSec: longword;
  EntOffset: word;
begin
 try
  with bootsec do
  begin
    if (N < 2) OR (N > countofclusters+1) then
    begin
      Debug(format('GetFAT error, wrong parameter: N %d (valid range is 2-%d)',
        [N, Countofclusters+1]), debugHigh);
      result:=0;
      exit;
    end;

    if Fattype = FAT16 then
      FATOffset:=N*2
    else if FATtype = FAT32 then
      FATOffset:=N*4
    else if FATtype = FAT12 then
      FATOffset:=N+(N div 2);

    nFATSec:=BPB_RsvdSecCnt + (FATno * FATsz) + (FATOffset div BPB_BytesPSec);
    if FFATsec <> nFatSec then
    begin
      ReadSec(nFATsec, 1, @FFATSecBuf, true);
      FFATsec:=nFATsec;
    end;

    EntOffset:=FATOffset MOD BPB_BytesPSec;
    if (FATtype = FAT12) AND (EntOffset = BPB_BytesPSec - 1) then
    begin
      { avoid sector boundary }
      ReadSec(nFATsec+1, 1, @FFATSecBuf[512], true);
    end;

    {  FAT sector has been read now... }
    if FATtype = FAT16 then
      value:=word(addr(FFATSecBuf[EntOffset])^)
    else if FATtype = FAT32 then
      value:=longword(addr(FFATSecBuf[EntOffset])^) and $0fffffff
    else if FATtype = FAT12 then
    begin
      value:=word(addr(FFatSecBuf[EntOffset])^);
      if (N AND 1 <> 0) then
        value:=value SHR 4
      else value:=value and $0fff;
    end;
    GetFAT:=value;
  end;
 except
   else GetFAT:=0;
 end;
end;


{ Get cluster mask for special cluster type (bad, end of file or used) }
function TFATdrive.GetClusterMask(clustype: byte): longword;
var
  mask: longword;
begin
  if clustype = clusFree then mask:=0;

  begin
    case FATtype of
      FAT12: begin
               if clustype = clusEOF then mask:=$0fff
                 else if clustype = clusBad then mask:=$0ff7;
             end;
      FAT16: begin
               if clustype = clusEOF then mask:=$ffff
                 else if clustype = clusBad then mask:=$fff7;
             end;
      FAT32: begin
               if clustype = clusEOF then mask:=$0fffffff
                 else if clustype = clusBad then mask := $0ffffff7;
             end;
    end;
  end;
  GetClusterMask:=mask;
end;


{ checks a cluster value for EOC (End Of Clusterchain) }
function TFATdrive.IsEOF(value: longword): boolean;
var
  res: boolean;
begin
  res:=false;
    if (FATtype=FAT12) AND (value >= $0ff8) then res:=true
      else if (FATtype=FAT16) AND (value >=$fff8) then res:=true
        else if (FATtype=FAT32) AND (value >= $0ffffff8) then res:=true;
  IsEOF:=res;
end;

function TFATdrive.Sec2Cluster(sec: longword): longword;
begin
  with BootSec do
    Sec2Cluster:=(sec-FirstDataSector) div BPB_SecPerClus+2;
end;

{ sector paramter is only used if cluster=0 (for FAT12/16) }
function TFATdrive.ReadDataSec(var cluster: longword; var sector: longword; var clussec: word; xferbuf: pointer): boolean;
var
  recsec: longword;
  res: boolean;
  secentry: word;
begin
 try
  res:=true;
  if (cluster > countofclusters+1) then
  begin
    Debug(format('ReadDataSec error, wrong parameter: cluster %d (valid range is 0-%d)',
      [cluster, countofclusters+1]), debugHigh);
    res:=false;
  end;

  if (res) then
  begin
    with BootSec do
    begin
      if cluster = 0 then { use sector paramter ? }
      begin
        if clussec > 0 then { read next sector ? }
        begin
          clussec:=0;
          inc(sector);
        end;
        recsec:=sector;
      end
      else begin { none root }
        if clussec >= BPB_SecPerClus then  { n鋍hsten Cluster laden? }
        begin
          if useFAT > 0 then cluster:=GetFAT(cluster, useFAT-1)
            else inc(cluster);
          if IsEOF(cluster) then res:=false     { EndOfDir! }
            else begin
              clussec:=0;
            end;
        end;
        if res then recsec:=cluster2sec(cluster) + clussec;
      end;

      if res then
      begin
        if FWorkSec <> recsec then
        begin
          ReadSec(recsec, 1, @FworkSecBuf, true);
          FWorkSec:=recsec;
        end;
        move(Fworksecbuf[0], xferbuf^, BPB_BytesPSec);
        inc(clussec);
      end;
    end;
  end;
  result:=res;
 except
   else result:=false;
 end;
end;


{ sector paramter is only used if cluster=0 (for FAT12/16) }
function TFATdrive.GetNextRecord(var cluster: longword; var sector: longword; var recno: word; xferbuf: pointer): boolean;
var
  recsec: longword;
  res: boolean;
  secentry: word;
begin
 try
  res:=true;
  if (cluster > countofclusters+1) then
  begin
    Debug(format('GetNextRecord error, wrong parameter: cluster %d (valid range is 0-%d)',
      [cluster, countofclusters+1]), debugHigh);
    res:=false;
  end;

  if (res) then
  begin
    with BootSec do
    begin
      if cluster = 0 then { use sector paramter ? }
      begin
        if recno >= (BPB_BytesPSec div 32) then { read next sector ? }
        begin
          recno:=0; inc(sector);
        end;
        recsec:=sector + (recno*32 div BPB_BytesPSec);
      end
      else begin { none root }
        {writeln('recno: ',recno, ' sec: ',recsec);}
        if recno >= (BytePerClus div 32) then  { n鋍hsten Cluster laden? }
        begin
          {write('getnxtrec cluster:',cluster);}
          if useFAT > 0 then cluster:=GetFAT(cluster, useFAT-1)
            else inc(cluster);
          {writeln('getnxtrec getfatcluster:',cluster);
          if iseof(cluster) then writeln('iseof!');
          readkey;}
          if IsEOF(cluster) then res:=false     { EndOfDir! }
            else begin
              {write('curr cluster is: ',cluster, ' next cluster is: ');
              writeln(cluster);
              readkey;}
              recno:=0;
            end;
        end;
        if res then recsec:=cluster2sec(cluster)+(recno*32 div BPB_BytesPSec);
      end;

      if res then
      begin
        if FWorkSec <> recsec then
        begin
          {writeln('neue sec:',recsec);}
          ReadSec(recsec, 1, @FworkSecBuf, true);
          FWorkSec:=recsec;
        end;
        secentry:=recno mod (BPB_BytesPSec div 32);
        move(Fworksecbuf[secentry*32], xferbuf^, 32);
        inc(recno);
      end;
    end;
  end;
  GetNextRecord:=res;
 except
   else GetNextRecord:=false;
 end;
end;


{ ermittelt langen Dateinamen an aktueller Position und gibt zugeh鰎igen kurzen Dateieintrag
  (DirEntry) zur點k }
function TFATdrive.GetLongName(var cluster: longword; var recsec: longword; var recno: word;
  entry: PDirEntry; var longname: string): boolean;
var
  oldcluster: longword;
  oldrecno: longword;
  chksum, sum: byte;
  res: boolean;
  slotno: byte;
  N: byte;
  uname: array[0..255] of word;
  len: byte;
  p: byte;
  lnentry: Tdirentry;
  i: integer;
  multibytebuf: array[0..510] of byte;
begin
  res:=true;

  with PLnDirEntry(entry)^ do
  begin
    if (DIR_Attr = $0f) AND (DIR_First = 0) AND (DIR_sig AND $40=$40) then
    begin
      { ---- long name dir entry found ------- }
      //N:=DIR_Sig AND (NOT $40);
      N:=18; // maximum is slotno=18
      slotno:=N; p:=N*13; len:=0;
      chksum:=DIR_chksum;
      { ---- check for valid long name entry... ------- }
      while (DIR_attr = $0f) AND (DIR_first = 0) {AND (DIR_Sig AND (NOT $40)=slotno)}
        AND (slotno > 0) AND (DIR_chksum = chksum) do
      begin
        if p >= 13 then dec(p,13);
        inc(len,13);
        move(DIR_LName1, uname[p+0], 10);
        move(DIR_LName2, uname[p+5], 12);
        move(DIR_LName3, uname[p+11], 4);

        dec(slotno);
        { ----- get next directory record .... ------- }
        if slotno > 0 then res:=GetNextRecord(cluster, recsec, recno, entry);
      end;

      { ------- long filename is build - get following short -------- }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -