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

📄 diskfs.pas

📁 国外著名恢复软件Drive_Rescue 公布的早期源码 版本是1.8 delphi6环境开发的。
💻 PAS
📖 第 1 页 / 共 5 页
字号:
function TFATAnalyser.ClusterType(FATtype: byte; value: longword): byte;
var
  res: byte;
begin
  if value = 0 then res:=clusFree
    else res:=clusUsed;
  begin
    case FATtype of
      FAT12: begin
               if value >= $0ff8 then res:=clusEOF
                 else if value >= $0ff1 then res:=clusBad;
             end;
      FAT16: begin
               if value >= $fff8 then res:=clusEOF
                 else if value >=$fff1 then res:=clusBad;
             end;
      FAT32: begin
               if value >= $0ffffff8 then res:=clusEOF
                 else if value >= $0ffffff1 then res:=clusBad;
             end;
    end;
  end;
  ClusterType:=res;
end;


function TFATAnalyser.IsBootSecB(p: pointer): boolean;
type
  tbuf= array[0..511] of byte;
var
  pbs: pbootsec;
  pbuf: ^tbuf;
  valid: boolean;
  i: integer;
begin
  valid:=false;
  pbs:=p; pbuf:=p;
  if (pbuf^[510]=$55) AND (pbuf^[511]=$aa) AND (pbuf^[0]=$eb) then
  begin
    for i:=8 to 12 do
    begin
      if (pbs^.BPB_BytesPSec) = word(2 SHL i)  then valid:=true;
    end;
  end;
  IsBootSecB:=valid;
end;

function TFATAnalyser.AreBootSecEqualB(p1, p2: pointer): boolean;
type
  pbuf= array[0..511] of byte;
var
  pbs1: pbootsec;
  pbs2: pbootsec;
  buf: ^pbuf;
begin
  result:=FALSE;
  pbs1:=p1;
  pbs2:=p2;

  if pbs1^.BPB_BytesPSec <> pbs2^.BPB_BytesPSec then exit;
  if pbs1^.BPB_SecPerClus <> pbs2^.BPB_SecPerClus then exit;
  if pbs1^.BPB_RsvdSecCnt <> pbs2^.BPB_RsvdSecCnt then exit;
  if pbs1^.BPB_NumFATs <> pbs2^.BPB_NumFATs then exit;
  if pbs1^.BPB_RootEntCnt <> pbs2^.BPB_RootEntCnt then exit;
  if pbs1^.BPB_TotSec16 <> pbs2^.BPB_TotSec16 then exit;
  if pbs1^.BPB_FATsz16 <> pbs2^.BPB_FATsz16 then exit;
  if pbs1^.BPB_SecPerTrk <> pbs2^.BPB_SecPerTrk then exit;
  if pbs1^.BPB_NumHeads <> pbs2^.BPB_NumHeads then exit;
  if pbs1^.BPB_HiddSec <> pbs2^.BPB_HiddSec then exit;
  if pbs1^.BPB_TotSec32 <> pbs2^.BPB_TotSec32 then exit;

  result:=TRUE;
end;

{ checks if entry is blank }
function TFATAnalyser.IsBlankEntry(entry: TDirEntry): boolean;
var
  noblanks: word;
  i: integer;
begin
  result:=FALSE;
  noblanks:=0;
  for i:=0 to sizeof(entry)-1 do
    if byte(pointer(longint(@entry)+i)^) <> 0  then inc(noblanks);
  if noblanks = 0 then result:=TRUE;
end;

function TFATAnalyser.DirEntriesValidC(drv: TfatDrive; clus, sec: longword): boolean;
var
  currclus: longword;
  recsec: longword;
  clussec: word;
  secbuf: array[0..511] of byte;
begin
  if clus = 11393 then
  begin
    //debug('root!', debugHigh);
  end;
  if drv.ReadDataSec(clus, sec, clussec, @secbuf[0]) then
  begin
    currclus:=clus; recsec:=sec;
    result:=DirEntriesValidB(@secbuf[0], 512, drv.CountOfClusters, drv.TotDataSec);
  end else result:=FALSE;
end;


{ sec paramter is only used if clus=0 ! (for FAT12/16) }
function TFATAnalyser.DirEntriesValidB(buf: pointer; bufsize: word;
  ValidClusterCount, ValidTotalDataSec: longword): boolean;
var
  no: integer;
  recno: word;
  entry: TDirEntry;
  shortname: shortstring;
  i: integer;
  entclus: longword;
  longfound: boolean;
  res: boolean;
begin
  recno:=0;
  result:=FALSE; longfound:=FALSE;
  for no:=1 to 16 do
  begin
    res:=GetNextRecordB(buf, bufsize, recno, @entry);
    if (NOT res) then exit;

    // check if first entry used => if not, this is NOT a directory...
    if no = 1 then if entry.DIR_Name[0]=0 then {IsBlankEntry(entry) then} exit;

    with TLnDirEntry(entry) do
      if ( ((DIR_Attr = $0f) AND (DIR_First = 0) AND (DIR_sig AND $40=$40) )
        OR ((DIR_Attr = $0f) AND (DIR_First = 0) AND longfound) ) then
    begin
      { Long file name entry found... }
      longfound:=TRUE;


    end else
    begin
      longfound:=FALSE;
      //debug(cnvname(@entry.dir_name), debugHigh);
      { short file name entry... }
      { check valid short filename (not valid are e.g. : '\', '/', ':', '*', '?', '"', '<', '>', '\') }
      for i:=0 to 10 do
      begin
        if (entry.DIR_Name[i] < $20) then
        begin
          if (i > 0) then exit;  { values less 20hex not legal }
          if entry.DIR_Name[0] <> $05 then exit; { only one case: KANJI lead byte => then deleted is 05hex, not 0E5hex! }
        end else if byte(entry.DIR_Name[i]) IN [$22, $2A, $2B, $2C, $2E, $2F, $3A, $3B, $3C, $3D, $3E, $3F, $5B, $5C, $5D, $7C] then exit;
      end;
      { check cluster value }
      entclus:=entry.DIR_FstClusLO OR (longint(entry.DIR_FstClusHI) SHL 16);
      if (entry.DIR_attr AND attrVolume <> 0) then
      begin
        if entclus <> 0 then exit;        // volume label must be cluster 0
      end else if (entclus < 2) OR (entclus > ValidClusterCount+1) then exit;
      { check attribute }
      if (entry.DIR_Attr AND 192) <> 0 then exit;
      { check file size }
      if longword(entry.DIR_FileSize div 512) > longword(ValidTotalDataSec) then exit;
      { check date / time }
      { write time/date (must be supported) }
      if entry.DIR_WrtTime <> 0 then
      begin
        if (entry.DIR_WrtTime AND 31) > 29 then exit;
        if ((entry.DIR_WrtTime SHR 5) AND 63) > 59 then exit;
        if (entry.DIR_WrtTime SHR 11) > 23 then exit;
      end;
      if entry.DIR_WrtDate <> 0 then
      begin
        if (entry.DIR_WrtDate AND 31 > 31) OR (entry.DIR_WrtDate AND 31 = 0) then exit;
        if (((entry.DIR_WrtDate SHR 5) AND 15) > 12) OR ((entry.DIR_WrtDate SHR 5) AND 15 = 0) then exit;
      end;
      if entry.DIR_CrtTime <> 0 then
      begin
        if (entry.DIR_CrtTime AND 31) > 29 then exit;
        if ((entry.DIR_CrtTime SHR 5) AND 63) > 59 then exit;
        if (entry.DIR_CrtTime SHR 11) > 23 then exit;
      end;
      if entry.DIR_CrtDate <> 0 then
      begin
        if (entry.DIR_CrtDate AND 31 > 31) OR (entry.DIR_CrtDate AND 31 = 0) then exit;
        if (((entry.DIR_CrtDate SHR 5) AND 15) > 12) OR ((entry.DIR_CrtDate SHR 5) AND 15 = 0) then exit;
      end;
      if entry.DIR_LstAccDate <> 0 then
      begin
        if (entry.DIR_LstAccDate AND 31 > 31) OR (entry.DIR_LstAccDate AND 31 = 0) then exit;
        if (((entry.DIR_LstAccDate SHR 5) AND 15) > 12) OR ((entry.DIR_LstAccDate SHR 5) AND 15 = 0) then exit;
      end;
    end;
  end;
  result:=TRUE;
end;


{ There should only be one "file" on the volume that has the volume attribute set, and that file must be in the root directory.
  This name of this file is actually the label for the volume. DIR_FstClusHI and DIR_FstClusLO must always be 0 for the volume label
  (no data clusters are allocated to the volume label file). }
// sec is only used if clus = 0 (for FAT12/16)
function TFATAnalyser.IsRootC(drv: TfatDrive; clus, sec: longword): boolean;
var
  no: integer;
  recno: word;
  currclus: longword;
  entry: TDirEntry;
  volfound: boolean;
  recsec: longword;
  res: boolean;
begin
  currclus:=clus; recsec:=sec;
  recno:=0;
  volfound:=FALSE;
  for no:=1 to (drv.BootSec.BPB_SecPerClus * 16) do
  begin
    res:=drv.GetNextRecord(currclus, recsec, recno, @entry);
    if (NOT res) then break;
    with TLnDirEntry(entry) do
      if NOT (DIR_Attr = $0f) AND (DIR_First = 0) AND (DIR_sig AND $40=$40) then  // no long file name...
    begin
      if (entry.DIR_attr AND attrVolume <> 0) AND (entry.DIR_FstClusHI = 0) AND (entry.DIR_FstClusLO = 0) then
      begin
        if volfound then    // more than one volume label => no root!
        begin
          result:=FALSE;
          exit;
        end else volfound:=TRUE;
      end;
    end;
  end;
  result:=volfound;
end;


function TFATAnalyser.IsDirC(drv: TfatDrive; clus, sec: longword): boolean;
var
  currclus: longword;
  recno: word;
  entry: TDirEntry;
  recsec: longword;
  res: boolean;
begin
  recno:=0; currclus:=clus; recsec:=sec;
  res:=drv.GetNextRecord(currclus, recsec, recno, @entry);
  if (res) AND (entry.DIR_attr AND attrSubDir <>0) AND (CnvName(@entry.DIR_name) = '.') then
  begin
    res:=drv.GetNextRecord(currclus, recsec, recno, @entry);
    if (res) then
    begin
      if (entry.DIR_attr AND attrSubDir <>0) AND (CnvName(@entry.DIR_name) = '..') then
      begin
        result:=TRUE;
        exit;
      end;
    end;
  end;
  result:=FALSE;
end;

{ checks if directory is empty }
function TFATAnalyser.IsDirEmptyC(drv: TfatDrive; clus, sec: longword): boolean;
var
  lfname: string;
  currclus, recsec: longword;
  res: boolean;
  recno: word;
  entry: TDirEntry;
begin
  result:=TRUE;
  recsec:=sec; currclus:=clus;
  recno:=2;
  res:=drv.FindNextEntry(currclus, recsec, recno, entry, lfname, FALSE);
  if res then result:=FALSE;
end;

function TFATAnalyser.IsFileC(drv: TfatDrive; scanclus: longword; var fileext: string; var datatype: byte): boolean;
var
  buf: pointer;
  res: boolean;
begin
  getmem(buf, drv.bootsec.BPB_SecPerClus*512);
  try
    res:=drv.ReadSec(drv.Cluster2Sec(scanclus), drv.bootsec.BPB_SecPerClus, buf, TRUE);
    if res then res:=filedet.IsFile(buf, drv.bootsec.BPB_SecPerClus*512, fileext, datatype)

  finally
    freemem(buf, drv.bootsec.BPB_SecPerClus*512);
  end;
  result:=res;
end;


function TFATAnalyser.GetNextRecordB(buf: pointer; bufsize: longword; var recno: word; xferbuf: pointer): boolean;
var
  recsec: longword;
  res: boolean;
  secentry: word;
begin
  if (recno+1) * 32 <= bufsize then
  begin
    move(pointer(longword(buf)+recno*32)^, xferbuf^, 32);
    inc(recno);
    result:=TRUE;
  end else result:=FALSE;
end;

function TFATAnalyser.IsDirB(buf: pointer; bufsize: longword; var cluster: longword): boolean;
var
  recno: word;
  entry: TDirEntry;
  res: boolean;
  clus: longword;
begin
  recno:=0;
  res:=GetNextRecordB(buf, bufsize, recno, @entry);
  if (res) AND (entry.DIR_attr AND attrSubDir <>0) AND (CnvName(@entry.DIR_name) = '.') then
  begin
    clus:=entry.DIR_FstClusLO OR (longint(entry.DIR_FstClusHI) SHL 16);
    res:=GetNextRecordB(buf, bufsize, recno, @entry);
    if (res) then
    begin
      if (entry.DIR_attr AND attrSubDir <>0) AND (CnvName(@entry.DIR_name) = '..') then
      begin
        cluster:=clus;
        result:=TRUE;
        exit;
      end;
    end;
  end;
  result:=FALSE;
end;

{ There should only be one "file" on the volume that has the volume attribute set, and that file must be in the root directory.
  This name of this file is actually the label for the volume. DIR_FstClusHI and DIR_FstClusLO must always be 0 for the volume label
  (no data clusters are allocated to the volume label file). }
// sec is only used if clus = 0 (for FAT12/16)
function TFATAnalyser.IsRootB(buf: pointer; bufsize: longword): boolean;
var
  no: integer;
  recno: word;
  entry: TDirEntry;
  volfound: boolean;
  res: boolean;
begin
  recno:=0;
  volfound:=FALSE;
  for no:=1 to bufsize DIV 32 do
  begin
    res:=GetNextRecordB(buf, bufsize, recno, @entry);
    if (NOT res) then break;
    with TLnDirEntry(entry) do
      if NOT (DIR_Attr = $0f) AND (DIR_First = 0) AND (DIR_sig AND $40=$40) then  // no long file name...
    begin
      if (entry.DIR_attr AND attrVolume <> 0) AND (entry.DIR_FstClusHI = 0) AND (entry.DIR_FstClusLO = 0) then
      begin
        if volfound then    // more than one volume label => no root!
        begin
          result:=FALSE;
          exit;
        end else volfound:=TRUE;
      end;
    end;
  end;
  result:=volfound;
end;


// checks for FAT beginning
function TFATAnalyser.IsFATbeginB(buf: pointer; bufsize: longword; FATtype: byte): boolean;
const
  media: array[1..8] of byte = ($F0, $F8, $F9, $FA, $FB, $FC, $FD, $FE);
   // $FF is also allowed but used for EOF mark by MS disk driver...
var
  i: integer;
  res: boolean;
begin
  result:=FALSE;
  // check BPB_Media byte value...
  for i:=1 to 8 do
  begin
    case FATtype of
      FAT12: res:= (pwordarray(buf)^[0]=$0F00 OR media[i]);
      FAT16: res:= (pwordarray(buf)^[0]=$FF00 OR media[i]);
      FAT32: res:= (plongarray(buf)^[0]=$0FFFFF00 OR media[i]);
    end;
    if res then
    begin
      result:=TRUE;
      exit;
    end;
  end;
end;

// get FAT entry number N (for specified buf and FAT type)
function TFATAnalyser.GetFATB(buf: pointer; bufsize: longword; FATtype: byte; N: longword): longword;
var
  offset: longword;
  value: longword;
begin
  if Fattype = FAT16 then
    offset:=N*2
  else if FATtype = FAT32 then
    offset:=N*4
  else if FATtype = FAT12 then
    offset:=N+(N div 2);

  if FATtype = FAT16 then
    value:=word((@pbytearray(buf)^[offset])^)
  else if FATtype = FAT32 then

⌨️ 快捷键说明

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