Spravovanie mena disku.

unit VolLabel; 
 
interface 
 
uses 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); 
 
implementation 
 
type 
  PRealModeRegs = ^TRealModeRegs; 
  TRealModeRegs = record 
   case 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); 
{ procedure invokes int 31h function 0300h to simulate a real mode } 
{ interrupt  from protected mode. } 
var 
  ErrorFlag: Boolean; 
begin 
  asm 
   mov ErrorFlag, 0      { assume success } 
   mov ax, 0300h          { function 300h } 
   mov bl, Int            { real mode interrupt to execute } 
   mov bh, 0              { required } 
   mov cx, 0              { stack words to copy, assume zero } 
   les di, Regs          { es:di = Regs } 
   int 31h                { DPMI int 31h } 
   jnc 
 
End              { carry flag set on error } 
 
 
Error: 
   mov ErrorFlag, 1      { return false on error } 
 
 
End: 
  end; 
  if ErrorFlag then 
   raise EDPMIError.Create('Failed to execute DPMI interrupt'); 
end; 
 
function DriveLetterToNumber(DriveLet: Char): Byte; 
{ function converts a character drive letter into its numerical equiv. } 
begin 
  if DriveLet in ['a'..'z'] then 
   DriveLet := Chr(Ord(DriveLet) -32); 
  if not (DriveLet in ['A'..'Z']) then 
   raise EConvertError.CreateFmt('Cannot convert %s to drive number', 
                                 [DriveLet]); 
  Result := Ord(DriveLet) - 64; 
end; 
 
procedure PadVolumeLabel(var Name: Str11); 
{ procedure pads Volume Label string with spaces } 
var 
  i: integer; 
begin 
  for i := Length(Name) + 1 to 11 do 
   Name := Name + ' '; 
end; 
 
function GetVolumeLabel(Drive: Char): Str11; 
{ function returns volume label of a disk } 
var 
  SR: TSearchRec; 
  DriveLetter: Char; 
  SearchString: String[7]; 
  P: Byte; 
begin 
  SearchString := Drive + ':\*.*'; 
  { find vol label } 
  if FindFirst(SearchString, faVolumeID, SR) = 0 then begin 
   P := Pos('.', SR.Name); 
   if P > 0 then begin                      { if it has a dot... } 
     Result := '          ';              { pad spaces between name } 
     Move(SR.Name[1], Result[1], P - 1);    { and extension } 
     Move(SR.Name[P + 1], Result[9], 3); 
   end 
   else begin 
     Result := SR.Name;                    { otherwise, pad to end } 
     PadVolumeLabel(Result); 
   end; 
  end 
  else 
   Result := ''; 
end; 
 
procedure DeleteVolumeLabel(Drv: Char); 
{ procedure deletes volume label from given drive } 
var 
  CurName: Str11; 
  FCB: TExtendedFCB; 
  ErrorFlag: WordBool; 
begin 
  ErrorFlag := False; 
  CurName := GetVolumeLabel(Drv);        { get current volume label } 
  FillChar(FCB, SizeOf(FCB), 0);        { initialize FCB with zeros } 
  with FCB do begin 
   ExtendedFCBflag := $FF;              { always } 
   Attr := faVolumeID;                  { Volume ID attribute } 
   DriveID := DriveLetterToNumber(Drv); { Drive number } 
   Move(CurName[1], FileName, 8);      { must enter volume label } 
   Move(CurName[9], FileExt, 3); 
  end; 
  asm 
   push ds                              { preserve ds } 
   mov ax, ss                          { put seg of FCB (ss) in ds } 
   mov ds, ax 
   lea dx, FCB                          { put offset of FCB in dx } 
   mov ax, 1300h                        { function 13h } 
   Call DOS3Call                        { invoke int 21h } 
   pop ds                              { restore ds } 
   cmp al, 00h                          { check for success } 
   je 
 
End 
 
 
Error:                              { set flag on error } 
   mov ErrorFlag, 1 
 
 
End: 
  end; 
  if ErrorFlag then 
   raise EInterruptError.Create('Failed to delete volume name'); 
end; 
 
procedure SetVolumeLabel(NewLabel: Str11; Drive: Char); 
{ procedure sets volume label of a disk.  Note that this procedure } 
{ deletes the current label before setting the new one.  This is } 
{ required for the set function to work. } 
var 
  Regs: TRealModeRegs; 
  FCB: PExtendedFCB; 
  Buf: Longint; 
begin 
  PadVolumeLabel(NewLabel); 
  if GetVolumeLabel(Drive) <> '' then          { if has label... } 
   DeleteVolumeLabel(Drive);                  { delete label } 
  Buf := GlobalDOSAlloc(SizeOf(PExtendedFCB));  { allocate real buffer } 
  FCB := Ptr(LoWord(Buf), 0); 
  FillChar(FCB^, SizeOf(FCB), 0);              { init FCB with zeros } 
  with FCB^ do begin 
   ExtendedFCBflag := $FF;                    { required } 
   Attr := faVolumeID;                        { Volume ID attribute } 
   DriveID := DriveLetterToNumber(Drive);      { Drive number } 
   Move(NewLabel[1], FileName, 8);            { set new label } 
   Move(NewLabel[9], FileExt, 3); 
  end; 
  FillChar(Regs, SizeOf(Regs), 0); 
  with Regs do begin                            { SEGMENT of FCB } 
   ds := HiWord(Buf);                          { offset = zero } 
   dx := 0; 
   ax := $1600;                                { function 16h } 
  end; 
  RealModeInt($21, Regs);                      { create file } 
  if (Regs.al <> 0) then                        { check for success } 
   raise EInterruptError.Create('Failed to create volume label'); 
end; 
 
end.