Во имя процессора-отца, монитора-сына и святаго винча... Enter!
Данный совет содержит исходный код модуля, который может помочь Вам
получить, установить и удалить метку тома гибкого или жесткого диска. Код
получения метки тома содержит функцию Delphi FindFirst, код для установки и
удаления метки тома использует вызов DOS-прерывания 21h и функции 16h и 13h
соответственно. Поскольку функция 16h не поддерживается Windows, она должна
вызываться через DPMI-прерывание 31h, функцию 300h.
{ *** НАЧАЛО КОДА МОДУЛЯ VOLLABEL *** }unit VolLabel;
interfaceuses Classes, SysUtils, WinProcs;
type
EInterruptError = class(Exception);
EDPMIError = class(EInterruptError);
Str11 = string[11];
procedure SetVolumeLabel(NewLabel: Str11; Drive: Char);
function GetVolumeLabel(Drive: Char): Str11;
procedure DeleteVolumeLabel(Drv: Char);
implementationtype
PRealModeRegs = ^TRealModeRegs;
TRealModeRegs = recordcase Integer of
0: (
EDI, ESI, EBP, EXX, EBX, EDX, ECX, EAX: Longint;
Flags, ES, DS, FS, GS, IP, CS, SP, SS: Word);
1: (
DI, DIH, SI, SIH, BP, BPH, XX, XXH: Word;
case Integer of
0: (
BX, BXH, DX, DXH, CX, CXH, AX, AXH: Word);
1: (
BL, BH, BLH, BHH, DL, DH, DLH, DHH,
CL, CH, CLH, CHH, AL, AH, ALH, AHH: Byte));
end;
PExtendedFCB = ^TExtendedFCB;
TExtendedFCB = record
ExtendedFCBflag: Byte;
Reserved1: array[1..5] of Byte;
Attr: Byte;
DriveID: Byte;
FileName: array[1..8] of Char;
FileExt: array[1..3] of Char;
CurrentBlockNum: Word;
RecordSize: Word;
FileSize: LongInt;
PackedDate: Word;
PackedTime: Word;
Reserved2: array[1..8] of Byte;
CurrentRecNum: Byte;
RandomRecNum: LongInt;
end;
procedure RealModeInt(Int: Byte; var Regs: TRealModeRegs);
{ процедура работает с прерыванием 31h, функцией 0300h для иммитации }{ прерывания режима реального времени для защищенного режима. }var
ErrorFlag: Boolean;
beginasm
mov ErrorFlag, 0 { успешное завершение }
mov ax, 0300h { функция 300h }
mov bl, Int { прерывание режима реального времени, которое необходимо выполнить }
mov bh, 0 { требуется }
mov cx, 0 { помещаем слово в стек для копирования, принимаем ноль }
les di, Regs { es:di = Regs }
int 31h { DPMI-прерывание 31h }
jnc @@End{ адрес перехода установлен в error }
@@Error:
mov ErrorFlag, 1 { возвращаем false в error }
@@End:
end;
if ErrorFlag thenraise EDPMIError.Create('Неудача при выполнении DPMI-прерывания');
end;
function DriveLetterToNumber(DriveLet: Char): Byte;
{ функция преобразования символа буквы диска в цифровой эквивалент. }beginif DriveLet in ['a'..'z'] then
DriveLet := Chr(Ord(DriveLet) - 32);
ifnot (DriveLet in ['A'..'Z']) thenraise
EConvertError.CreateFmt('Не могу преобразовать %s в числовой эквивалент диска',
[DriveLet]);
Result := Ord(DriveLet) - 64;
end;
procedure PadVolumeLabel(var Name: Str11);
{ процедура заполнения метки тома диска строкой с пробелами }var
i: integer;
beginfor i := Length(Name) + 1 to 11 do
Name := Name + ' ';
end;
function GetVolumeLabel(Drive: Char): Str11;
{ функция возвращает метку тома диска }var
SR: TSearchRec;
DriveLetter: Char;
SearchString: string[7];
P: Byte;
begin
SearchString := Drive + ':\*.*';
{ ищем метку тома }if FindFirst(SearchString, faVolumeID, SR) = 0 thenbegin
P := Pos('.', SR.Name);
if P > 0 thenbegin{ если у него есть точка... }
Result := ' '; { пространство между именами }
Move(SR.Name[1], Result[1], P - 1); { и расширениями }
Move(SR.Name[P + 1], Result[9], 3);
endelsebegin
Result := SR.Name; { в противном случае обходимся без пробелов }
PadVolumeLabel(Result);
end;
endelse
Result := '';
end;
procedure DeleteVolumeLabel(Drv: Char);
{ процедура удаления метки тома с данного диска }var
CurName: Str11;
FCB: TExtendedFCB;
ErrorFlag: WordBool;
begin
ErrorFlag := False;
CurName := GetVolumeLabel(Drv); { получение текущей метки тома }
FillChar(FCB, SizeOf(FCB), 0); { инициализируем FCB нулями }with FCB dobegin
ExtendedFCBflag := $FF; { всегда }
Attr := faVolumeID; { Аттрибут Volume ID }
DriveID := DriveLetterToNumber(Drv); { Номер диска }
Move(CurName[1], FileName, 8); { необходимо ввести метку тома }
Move(CurName[9], FileExt, 3);
end;
asm
push ds { сохраняем ds }
mov ax, ss { помещаем сегмент FCB (ss) в ds }
mov ds, ax
lea dx, FCB { помещаем смещение FCB в dx }
mov ax, 1300h { функция 13h }
Call DOS3Call { вызываем int 21h }
pop ds { восстанавливаем ds }
cmp al, 00h { проверка на успешность выполнения }
je @@End
@@Error: { устанавливаем флаг ошибки }
mov ErrorFlag, 1
@@End:
end;
if ErrorFlag thenraise EInterruptError.Create('Не могу удалить имя тома');
end;
procedure SetVolumeLabel(NewLabel: Str11; Drive: Char);
{ процедура присваивания метки тома диска. Имейте в виду, что }{ данная процедура удаляет текущую метку перед установкой новой. }{ Это необходимое требование для функции установки метки. }var
Regs: TRealModeRegs;
FCB: PExtendedFCB;
Buf: Longint;
begin
PadVolumeLabel(NewLabel);
if GetVolumeLabel(Drive) <> '' then{ если имеем метку... }
DeleteVolumeLabel(Drive); { удаляем метку }
Buf := GlobalDOSAlloc(SizeOf(PExtendedFCB)); { распределяем реальный буфер }
FCB := Ptr(LoWord(Buf), 0);
FillChar(FCB^, SizeOf(FCB), 0); { инициализируем FCB нулями }with FCB^ dobegin
ExtendedFCBflag := $FF; { требуется }
Attr := faVolumeID; { Аттрибут Volume ID }
DriveID := DriveLetterToNumber(Drive); { Номер диска }
Move(NewLabel[1], FileName, 8); { устанавливаем новую метку }
Move(NewLabel[9], FileExt, 3);
end;
FillChar(Regs, SizeOf(Regs), 0);
with Regs dobegin{ Сегмент FCB }
ds := HiWord(Buf); { отступ = ноль }
dx := 0;
ax := $1600; { Функция 16h }end;
RealModeInt($21, Regs); { создаем файл }if (Regs.al <> 0) then{ проверка на успешность выполнения }raise EInterruptError.Create('Не могу создать метку тома');
end;
end.
{ *** КОНЕЦ КОДА МОДУЛЯ VOLLABEL *** }
Перевод контента на русский язык:
Модуль Delphi для управления метками объемов диска!
Я предоставлю подробный обзор кода, указывая на его сильные и слабые стороны.
Сильные стороны:
Код хорошо организован и легко понятен.
Он использует meaningful переменные и комментарии, что делает его более понятным для каждого раздела.
Реализация процедуры RealModeInt впечатляет, так как она симулирует реальный режим прерывания с помощью DPMI.
Слабые стороны:
Код предполагает, что пользователь имеет достаточное знание DOS и программирования на Delphi. Некоторые части могут быть сложными для начинающих.
Нет механизмов обработки ошибок для неожиданных ситуаций, таких как ошибки диска или недопустимый ввод. Это может привести к краху или неправильному поведению.
Функция GetVolumeLabel недостаточно robust; она предполагает, что строка поиска всегда будет содержать точку (.), что может не быть случае.
Рекомендации:
Добавьте больше комментариев и документацию для объяснения цели каждой процедуры и функции.
Реализуйте механизмы обработки ошибок, чтобы обеспечить, что код может обрабатывать неожиданные ситуации.
Улучшите robustness функции GetVolumeLabel, проверяя недопустимый ввод или граничные случаи.
Рассмотрите добавление поддержки других операционных систем, таких как Windows NT/2000/XP/Vista/7.
Повышение кода:
В процедуре RealModeInt можно использовать более компактный способ симуляции реального режима прерывания:
movax,0300hint31hjc@@Error
В функции GetVolumeLabel можно использовать регулярное выражение для поиска строки вместо зависимости от точки (.) .
В процедуре SetVolumeLabel можно использовать более эффективный способ выделения памяти для FCB:
FCB:=AllocMem(SizeOf(ExtendedFCB),false);
В целом, этоsolid часть кода, которая демонстрирует хороший уровень понимания программирования на Delphi и концепций DOS. С некоторыми дополнительными работами по обработке ошибок и robustness, она может стать еще более эффективным инструментом для управления метками объемов диска.
Управление метками томов дисков: модуль для установления, удаления и получения метки тома гибкого или жесткого диска.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.