Работа с длинными именами файлов под ГОЛЫМ ДОСОМ
13 марта 1998 года
В этом модуле реализованы функции FindFirst и FindNext, но не простые, а работающие с длинными именами файлов под ГОЛЫМ ДОСОМ. Формат длинных имен, насколько я помню, узнавался методом высоконаучного тыка, так что никаких гарантий.
Писал очень давно, и сейчас даже откомпилировать не смог, так как не нашел модуля uni2dos. Зато вспомнил, что он делает :) Он перекодирует строку из Unicode в DOS кодировку. Таблица Unicodе для русских символов приведена тут.
Код:
uses uni2dos;
type TStr3=Array[1..3] of Char;
TStr8=Array[1..8] of Char;
TStr10=Array[1..10] of Char;
type TSector0 = Record
Jump : Array[1..3] of Char;
{ NEAR-переход на код загрузки }
OEMName : Array[1..8] of Char;
{ OEM-имя компании и версия системы }
SectSize : Word;
{ байт на сектор }
ClustSize : Byte;
{ секторов на единицу распределения (кластер) }
ResSecs : Word;
{ резервных секторов (секторов перед первой FAT) }
FatCnt : Byte;
{ число таблиц FAT }
RootSiz : Word;
{ макс.число 32-байтовых элементов корневого оглавления }
TotSecs : Word;
{ общее число секторов на носителе (раздел DOS) }
Media : Byte;
{ дескриптор носителя (то же, что 1-й байт FAT) }
FatSize : Word;
{ число секторов в одной FAT }
TrkSecs : Word;
{ секторов на дорожку (цилиндр) }
HeadCnt : Word;
{ число головок чтения/записи (поверхностей) }
HidnSec : Word;
{ спрятанных секторов (исп. в схемах разделения) }
Ostatok : Array[1..486] of Char;
{ Остаток, что-бы сюда можно было читать сектор }
End;
type TFile = Record
Name : TStr8; { Имя файла }
Ext : TStr3; { Расширение }
Attr : Byte; { Атрибут файла }
Reserv : TStr10; { Резерв }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
ClstrNo : Word;
{ номер начального кластера данных (связь с FAT ) }
Size : LongInt; { размер файла в байтах }
End;
type TLongSearchRec = Record
Name : TStr8; { Имя файла }
LongName : String; { Длиное имя файла }
Ext : TStr3; { Расширение }
Attr : Byte; { Атрибут файла }
Reserv : TStr10; { Резерв }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
ClstrNo : Word;
{ номер начального кластера данных (связь с FAT ) }
Size : LongInt; { размер файла в байтах }
FPosInSec : Integer; { Позиция - в секторе }
FSecPos : Integer; { Позиция - сектор }
FMask : String; { Маска для поиска }
FAttr : Byte; { Путь заданный в FindFirst }
End;
type TDTA = Record
Reserved : Array[1..$15] of Byte;
{ Зарезервированно для FindNext }
Attr : Byte;
{ Атрибут файла }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
Size : LongInt;
{ размер файла в байтах }
Name : Array[1..13] of Char;
{ Имя файла + . +расширение }
End;
type TDir=Array[0..15] of TFile;
var s0 : TSector0;
dir : TDir;
Root : Word;
I : Word;
Search : TLongSearchRec;
LongDosError : Integer;
SecPerCat : Integer;
DTA : TDTA; { Текущая DTA }
Function ReadSector(A:Pointer;Disk:Byte;Count:Word;Sector:Word):Boolean;
var Error :Word;
Offs :Word;
Begin
Offs:=Word(A);
Error:=0;
asm
mov al,[Disk] {Номер диска 0-A}
mov cx,[Count] {Счетчик считываемых символов}
mov dx,[Sector] {Начальный сектор}
mov bx,[Offs]
int 25h
pop dx
je @nError
mov ax,1
mov [Error],ax
@nError:
end;
if Error=0 then ReadSector:=True
else ReadSector:=False;
End;
{ Получаем длиное имя файла #################################################}
function GetUniLFN(I:Word):String;
var Str,Str0,Str1:String;
Flag:Boolean;
Len:Integer;
Begin
Flag:=true;Str0:=#255+#255;Str:='';Str1:='';
While flag do
Begin
Str1:=copy(Dir[I-1].Name,2,7)+Dir[I-1].Ext+
copy(Dir[I-1].Reserv,3,8)+char(Dir[I-1].Time)+
char(Dir[I-1].Time shr 8)+char(Dir[I-1].Date)+
char(Dir[I-1].Date shr 8)+char(Dir[I-1].Size)+
char(Dir[I-1].Size shr 8)+char(Dir[I-1].Size shr 16)+
char(Dir[I-1].Size shr 24);
Len:=pos(Str0,Str1);
If Len<>0 then Begin Flag:=False; Str:=Str+copy(Str1,1,Len); End
else Begin
dec(i);
Str:=Str+Str1;
if Dir[I].Attr<>15 then Flag:=False;
End;
End;
GetUniLFN:=Str;
End;
{ Long Find First ###########################################################}
Procedure LongFindFirst(Path:String;Attr:Word;var SR:TLongSearchRec);
var I,Sec :Integer;
Drive :Word; { Номер диска }
NameSeg,NameOfs :Word; { Адрес строки для поиска }
ParentDir :String; { Родительский каталог }
Sector,InSect,Data :LongInt;
{ Сектор, и позиция каталоговой записи }
DTASeg,DTASize,DTAOfs :Word; { Адрес локальгого DTA }
Begin
LongDOSError:=0;
{Drive:=Path[1];} Drive:=0; { Получаем имя диска }
ParentDir:=copy(Path,4,Length(Path)-1); { Выделим родительский каталог }
If not ReadSector(@s0,Drive,1,0) then Exit;
If Pos('\',ParentDir)=0 then
Begin { Если ищем в корне #################################################}
Path:=Path+#0;
NameSeg:=Seg(Path);NameOfs:=Ofs(Path)+1;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ax,[NameSeg]
mov ds,ax
mov dx,[NameOfs]
mov ah,$4E { Функция DOS - найти первый файл }
mov cx,Attr { Аттрибуты файла }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
{ Номер сектора,где находится каталог с именем }
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
If not ReadSector(@dir,0,1,Root+Sector) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End
else
Begin { Если ищем не в корне ##############################################}
Path:=Path+#0;
NameSeg:=Seg(Path);NameOfs:=Ofs(Path)+1;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ax,[NameSeg]
mov ds,ax
mov dx,[NameOfs]
mov ah,$4E { Функция DOS - найти первый файл }
mov cx,Attr { Аттрибуты файла }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Sector:=Sector+DTA.Reserved[16]+256*DTA.Reserved[17]-3;
{ Номер сектора,где находится каталог с именем }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
Data:=Root+(s0.RootSiz*32) div s0.SectSize;
If not ReadSector(@dir,0,1,Data+Sector) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End;
End;
{ Long Find Next ############################################################}
Procedure LongFindNext(var SR:TLongSearchRec);
var
Drive :Word; { Номер диска }
Sector,InSect,Data :LongInt; { Сектор, и позиция каталоговой записи }
DTASeg,DTASize,DTAOfs :Word; { Адрес локальгого DTA }
Begin
Drive:=0;
LongDOSError:=0;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov dx,bx
mov ah,$4F { Функция DOS - найти первый файл }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Sector:=Sector+DTA.Reserved[16]+256*DTA.Reserved[17]-3;
{ Номер сектора,где находится каталог с именем }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
Data:=Root+(s0.RootSiz*32) div s0.SectSize;
If not ReadSector(@dir,0,1,Data) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End;
Begin
WriteLn;
InitUni;
LongFindFirst('A:\1\*.*',$FFFF,Search);
While LongDosError=0 do
Begin
WriteLn(Search.Name+' '+Search.Ext+' ',Search.Size:8,' ',
Search.FPosInSec:8,' ',Search.FSecPos:8,' ',Search.LongName);
LongFindNext(Search);
Search.LongName:=copy(Search.LongName,1,30);
End;
End.
type TStr3=Array[1..3] of Char;
TStr8=Array[1..8] of Char;
TStr10=Array[1..10] of Char;
type TSector0 = Record
Jump : Array[1..3] of Char;
{ NEAR-переход на код загрузки }
OEMName : Array[1..8] of Char;
{ OEM-имя компании и версия системы }
SectSize : Word;
{ байт на сектор }
ClustSize : Byte;
{ секторов на единицу распределения (кластер) }
ResSecs : Word;
{ резервных секторов (секторов перед первой FAT) }
FatCnt : Byte;
{ число таблиц FAT }
RootSiz : Word;
{ макс.число 32-байтовых элементов корневого оглавления }
TotSecs : Word;
{ общее число секторов на носителе (раздел DOS) }
Media : Byte;
{ дескриптор носителя (то же, что 1-й байт FAT) }
FatSize : Word;
{ число секторов в одной FAT }
TrkSecs : Word;
{ секторов на дорожку (цилиндр) }
HeadCnt : Word;
{ число головок чтения/записи (поверхностей) }
HidnSec : Word;
{ спрятанных секторов (исп. в схемах разделения) }
Ostatok : Array[1..486] of Char;
{ Остаток, что-бы сюда можно было читать сектор }
End;
type TFile = Record
Name : TStr8; { Имя файла }
Ext : TStr3; { Расширение }
Attr : Byte; { Атрибут файла }
Reserv : TStr10; { Резерв }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
ClstrNo : Word;
{ номер начального кластера данных (связь с FAT ) }
Size : LongInt; { размер файла в байтах }
End;
type TLongSearchRec = Record
Name : TStr8; { Имя файла }
LongName : String; { Длиное имя файла }
Ext : TStr3; { Расширение }
Attr : Byte; { Атрибут файла }
Reserv : TStr10; { Резерв }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
ClstrNo : Word;
{ номер начального кластера данных (связь с FAT ) }
Size : LongInt; { размер файла в байтах }
FPosInSec : Integer; { Позиция - в секторе }
FSecPos : Integer; { Позиция - сектор }
FMask : String; { Маска для поиска }
FAttr : Byte; { Путь заданный в FindFirst }
End;
type TDTA = Record
Reserved : Array[1..$15] of Byte;
{ Зарезервированно для FindNext }
Attr : Byte;
{ Атрибут файла }
Time : Word;
{ время создания/модификации в формате filetime }
Date : Word;
{ дата создания/модификации в формате filetime }
Size : LongInt;
{ размер файла в байтах }
Name : Array[1..13] of Char;
{ Имя файла + . +расширение }
End;
type TDir=Array[0..15] of TFile;
var s0 : TSector0;
dir : TDir;
Root : Word;
I : Word;
Search : TLongSearchRec;
LongDosError : Integer;
SecPerCat : Integer;
DTA : TDTA; { Текущая DTA }
Function ReadSector(A:Pointer;Disk:Byte;Count:Word;Sector:Word):Boolean;
var Error :Word;
Offs :Word;
Begin
Offs:=Word(A);
Error:=0;
asm
mov al,[Disk] {Номер диска 0-A}
mov cx,[Count] {Счетчик считываемых символов}
mov dx,[Sector] {Начальный сектор}
mov bx,[Offs]
int 25h
pop dx
je @nError
mov ax,1
mov [Error],ax
@nError:
end;
if Error=0 then ReadSector:=True
else ReadSector:=False;
End;
{ Получаем длиное имя файла #################################################}
function GetUniLFN(I:Word):String;
var Str,Str0,Str1:String;
Flag:Boolean;
Len:Integer;
Begin
Flag:=true;Str0:=#255+#255;Str:='';Str1:='';
While flag do
Begin
Str1:=copy(Dir[I-1].Name,2,7)+Dir[I-1].Ext+
copy(Dir[I-1].Reserv,3,8)+char(Dir[I-1].Time)+
char(Dir[I-1].Time shr 8)+char(Dir[I-1].Date)+
char(Dir[I-1].Date shr 8)+char(Dir[I-1].Size)+
char(Dir[I-1].Size shr 8)+char(Dir[I-1].Size shr 16)+
char(Dir[I-1].Size shr 24);
Len:=pos(Str0,Str1);
If Len<>0 then Begin Flag:=False; Str:=Str+copy(Str1,1,Len); End
else Begin
dec(i);
Str:=Str+Str1;
if Dir[I].Attr<>15 then Flag:=False;
End;
End;
GetUniLFN:=Str;
End;
{ Long Find First ###########################################################}
Procedure LongFindFirst(Path:String;Attr:Word;var SR:TLongSearchRec);
var I,Sec :Integer;
Drive :Word; { Номер диска }
NameSeg,NameOfs :Word; { Адрес строки для поиска }
ParentDir :String; { Родительский каталог }
Sector,InSect,Data :LongInt;
{ Сектор, и позиция каталоговой записи }
DTASeg,DTASize,DTAOfs :Word; { Адрес локальгого DTA }
Begin
LongDOSError:=0;
{Drive:=Path[1];} Drive:=0; { Получаем имя диска }
ParentDir:=copy(Path,4,Length(Path)-1); { Выделим родительский каталог }
If not ReadSector(@s0,Drive,1,0) then Exit;
If Pos('\',ParentDir)=0 then
Begin { Если ищем в корне #################################################}
Path:=Path+#0;
NameSeg:=Seg(Path);NameOfs:=Ofs(Path)+1;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ax,[NameSeg]
mov ds,ax
mov dx,[NameOfs]
mov ah,$4E { Функция DOS - найти первый файл }
mov cx,Attr { Аттрибуты файла }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
{ Номер сектора,где находится каталог с именем }
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
If not ReadSector(@dir,0,1,Root+Sector) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End
else
Begin { Если ищем не в корне ##############################################}
Path:=Path+#0;
NameSeg:=Seg(Path);NameOfs:=Ofs(Path)+1;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ax,[NameSeg]
mov ds,ax
mov dx,[NameOfs]
mov ah,$4E { Функция DOS - найти первый файл }
mov cx,Attr { Аттрибуты файла }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Sector:=Sector+DTA.Reserved[16]+256*DTA.Reserved[17]-3;
{ Номер сектора,где находится каталог с именем }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
Data:=Root+(s0.RootSiz*32) div s0.SectSize;
If not ReadSector(@dir,0,1,Data+Sector) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End;
End;
{ Long Find Next ############################################################}
Procedure LongFindNext(var SR:TLongSearchRec);
var
Drive :Word; { Номер диска }
Sector,InSect,Data :LongInt; { Сектор, и позиция каталоговой записи }
DTASeg,DTASize,DTAOfs :Word; { Адрес локальгого DTA }
Begin
Drive:=0;
LongDOSError:=0;
DTAOfs:=Ofs(DTA);DTASeg:=Seg(DTA);DTASize:=Sizeof(DTA);
asm { FindFirst - заполняем }
push ds
mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov dx,bx
mov ah,$4F { Функция DOS - найти первый файл }
int 21h
jnc @FilesF
mov ax,$FF
mov [LongDOSError],ax
jmp @AsmEnd
@FilesF: mov ah,$2f { Получим адрес текущей DTA }
int 21h
mov ax,es { И скопируем ее в нашу локальную DTA }
mov ds,ax
mov si,bx
mov di,[DTAOfs]
mov es,[DTASeg]
mov cx,[DTASize]
cld
rep movsb
@AsmEnd: pop ds
end; { В DTA.Reserved[14] можно узнать номер найденой записи в каталоге}
If LongDOSError<>0 then Exit;
Sector:=trunc((DTA.Reserved[14]+256*DTA.Reserved[15])/(s0.SectSize shr 5));
InSect:=(DTA.Reserved[14]+256*DTA.Reserved[15])-Sector*(s0.SectSize shr 5);
{ Номер записи в секторе }
Sector:=Sector+DTA.Reserved[16]+256*DTA.Reserved[17]-3;
{ Номер сектора,где находится каталог с именем }
Root:=s0.ResSecs+s0.FatSize*s0.FatCnt; { Вычисляем номер сектора с корнем }
Data:=Root+(s0.RootSiz*32) div s0.SectSize;
If not ReadSector(@dir,0,1,Data) then Exit; { Читаем сектор }
SR.Name:=dir[InSect].Name; { Заполнаяем TLongSearchRec }
SR.Ext:=dir[InSect].Ext;
SR.Attr:=dir[InSect].Attr;
SR.Reserv:=dir[InSect].Reserv;
SR.Time:=dir[InSect].Time;
SR.Date:=dir[InSect].Date;
SR.ClstrNo:=dir[InSect].ClstrNo;
SR.Size:=dir[InSect].Size;
{ Теперь смотрим длиное имя }
If (InSect>0) and (dir[InSect-1].attr=15) then
SR.LongName:=UniToDos(GetUniLFN(InSect))
else SR.LongName:=dir[InSect].Name+'.'+dir[InSect].Ext;
End;
Begin
WriteLn;
InitUni;
LongFindFirst('A:\1\*.*',$FFFF,Search);
While LongDosError=0 do
Begin
WriteLn(Search.Name+' '+Search.Ext+' ',Search.Size:8,' ',
Search.FPosInSec:8,' ',Search.FSecPos:8,' ',Search.LongName);
LongFindNext(Search);
Search.LongName:=copy(Search.LongName,1,30);
End;
End.