ISO9660 Header (VTOC) auslesen?

Dalai

Grand Admiral Special
Mitglied seit
14.06.2004
Beiträge
7.420
Renomée
262
Standort
Meiningen, Thüringen
Hey Leute,

auch wenn mein bisheriges Problem noch nicht gelöst wurde, hab ich schon wieder eine neue Frage.

Ich muss den ISO9660 Header auslesen, und zwar unter DOS. Genauer gesagt geht es mir um eine CD-Bezeichnung, die ich auslesen will.
Wie mach ich das am besten bzw. am einfachsten?

Bisher habe ich (vereinfacht) folgenden Code (Pascal):
Code:
begin
    for Drive:= 'A' to 'Z' do
    begin
        {wenn das Laufwerk gültig und ein CD-ROM ist....}
        if (IsDriveValid(DriveToByte(Drive)) AND IsCDROM(DriveToByte(Drive))) then
        begin
            {...prüfen, ob Laufwerk bereit und gleichzeitig den Datenträgernamen auslesen}
            FindFirst(Drive + ':\*.*', $8, VolLabel);  {<<-- dort ist schon "das Problem"}
            if (DosError = 0) then
            begin
                {hier kommt dann mein restlicher Code, der hier nicht weiter interessiert}
            end;
        end;
    end;
end.


{ ---- nachfolgend die im Hauptprogramm benutzten Funktionen, nur zur Referenz ---- }

function DriveToByte(Drive: Char): byte;
begin
  DriveToByte:= 255;
  case Drive of
    'A': DriveToByte:= 1;
    'B': DriveToByte:= 2;
    'C': DriveToByte:= 3;
    'D': DriveToByte:= 4;
    'E': DriveToByte:= 5;
    'F': DriveToByte:= 6;
    'G': DriveToByte:= 7;
    'H': DriveToByte:= 8;
    'I': DriveToByte:= 9;
    'J': DriveToByte:= 10;
    'K': DriveToByte:= 11;
    'L': DriveToByte:= 12;
    'M': DriveToByte:= 13;
    'N': DriveToByte:= 14;
    'O': DriveToByte:= 15;
    'P': DriveToByte:= 16;
    'Q': DriveToByte:= 17;
    'R': DriveToByte:= 18;
    'S': DriveToByte:= 19;
    'T': DriveToByte:= 20;
    'U': DriveToByte:= 21;
    'V': DriveToByte:= 22;
    'W': DriveToByte:= 23;
    'X': DriveToByte:= 24;
    'Y': DriveToByte:= 25;
    'Z': DriveToByte:= 26;
  end;
end;


{ --- Die beiden folgenden Funktion hab ich mir aus einem Program namens Free SPace (FSP) gemopst ----}
FUNCTION IsDriveValid (cDrive : BYTE): BOOLEAN;
{ ** portion of a SWAG snippet -- modified for FSP

  Parameters: cDrive is the drive letter to check: 1 to 26 (A to Z).

  Returns: Function returns True only if the given drive is valid, and it
  is not SUBSTituted.
}
VAR
  rCPU: DOS. REGISTERS;
  bLocal,
  bSUBST : BOOLEAN;
BEGIN
  bLocal := FALSE;
  bSUBST := FALSE;
  IsDriveValid := FALSE;

  rCPU. BX := cDrive;
  rCPU. AX := $4409;
  { --- Call the Dos IOCTL (InOutConTroL)-Functions --- }
  Intr ($21, rCPU);
  IF NOT ((rCPU. AX AND fCarry) = fCarry)
    THEN BEGIN { --- drive is valid, check status --- }
      bLocal := ((rCPU. DX AND $1000) = $0000);
      IF bLocal THEN bSUBST := ((rCPU. DX AND $8000) = $8000);
      IF (NOT bSUBST) THEN IsDriveValid := TRUE;
    END;
END; { IsDriveValid }


FUNCTION IsCDROM (DRIVE: BYTE): BOOLEAN;
(* FROM SWAG *)
CONST
  CDROM_INTERRUPT = $2f;
VAR
  Regs : REGISTERS;

  { Returns a code indicating whether a particular logical  }
  { unit is supported by the Microsoft CD-ROM Extensions    }
  { module (MSCDEX).                                        }

BEGIN
  Regs. AX := $150b;
  Regs. BX := $0000;
  Regs. CX := DRIVE-1;
  Intr (CDROM_INTERRUPT, Regs);
  IsCDROM := (Regs. AX <> $0000) AND (Regs. BX = $adad);
END;

Problem bei diesem Code ist, dass das
Code:
FindFirst(Drive + ':\*.*', $8, VolLabel);
nur eine Bezeichnung im Format 8.3 zurückgibt. Nun weiß aber jeder, der schonmal eine CD gebrannt hat, dass die Bezeichnung deutlich länger sein kann (laut ISO9660-Spezifikation bis 32 Zeichen).

Wie komme ich also an diesen ISO9660-Header ran, um die volle Bezeichnung auszulesen?
Das beste wäre eine Funktion, die mir bei übergebenem Laufwerksbuchstaben (oder entsprechendem Integer-Wert) die passende Bezeichnung zurückliefert. Diese Funktion kann meinetwegen auch in Assembler sein.

Danke im Voraus für Vorschläge und Hilfe etc. pp.

MfG Dalai
 
Also das sollte irgendwie so aussehen (und einen Pointer auf den Inhalt des ersten Sektors liefern):

Code:
FUNCTION GetVTOC (DRIVE: BYTE): Pointer;
CONST
  CDROM_INTERRUPT = $2f;
VAR
  Regs : REGISTERS;
  res: Pointer;

BEGIN
  GetMem(res, 2048);

  Regs. AX := $1505;
  Regs. CX := DRIVE-1;
  Regs. DX := 0;

  Regs. ES := Ofs(res);
  Regs. BS := Seg(res);

  Intr (CDROM_INTERRUPT, Regs);

  if fCarry <> 0 Then
  begin
    FreeMem(res);
    GetVTOC := nil;
  else
    GetVTOC := res;
  end;

END;

Wenn Du ein Ergebnis ungleich NIL bekommst, ist der Pointer gültig (hinterher das FreeMem nicht vergessen). Das Ganze ist aber nicht getestet und somit arg improvisiert, da ich hier grad kein Pascal habe ...

Gruß,
BoMbY
 
Zuletzt bearbeitet:
Code:
FUNCTION GetVTOC (DRIVE: BYTE): Pointer;
CONST
  CDROM_INTERRUPT = $2f;
VAR
  Regs : REGISTERS;
  res: Pointer;

BEGIN
  GetMem(res, 2048);

  Regs. AX := $1505;
  Regs. CX := DRIVE-1;
  Regs. DX := 0;

  Regs. ES := Ofs(res);
  Regs. B[B]X[/B] := Seg(res); [B]{oder soll das auch Regs.ES sein?}[/B]

  Intr (CDROM_INTERRUPT, Regs);

  if fCarry <> 0 Then
  begin
    FreeMem(res[B], 2048[/B]);
    GetVTOC := nil;
  [B]end[/B]
  else
    GetVTOC := res;
END;

Ich hab das mal korrigiert ;) Die fetten Bereiche sind die korrigierten.

Wenn Du ein Ergebnis ungleich NIL bekommst, ist der Pointer gültig
Soweit ist mit das klar.

Code:
var toc: Pointer;
begin
    for Drive:= 'A' to 'Z' do
    begin
        {wenn das Laufwerk gültig und ein CD-ROM ist....}
        if (IsDriveValid(DriveToByte(Drive)) AND IsCDROM(DriveToByte(Drive))) then
        begin
            {...prüfen, ob Laufwerk bereit und gleichzeitig den Datenträgernamen auslesen}
            toc:= GetVTOC(DriveToByte(Drive));
            if toc <> nil then
            begin
                GetMem(toc, 2048);
                [B]{Wie gehts hier weiter?}[/B]
                FreeMem(toc, 2048);
            end;
        end;
    end;
end.

Wie verwende ich den angeforderten Speicher? Mit PChar? Oder mit dem @-Operator?
Sorry, wenn ich aufm Schlauch steh, aber mit Adressen und Pointern hab ich noch nie gerne gearbeitet (deswegen programmiere ich auch kein C/++ ;))

MfG Dalai
 
Zuletzt bearbeitet:
Das GetMem(toc, 2048 ) vor {Wie gehts hier weiter?} muss weg, das macht doch schon FUNCTION GetVTOC.

Schau doch einfach mal mit dem Debugger in den Bereich, auf den der Pointer zeigt.
Was ist VolLabel für ein Typ? Array of char oder string?
Jedenfalls den Bereich, auf den der Pointer zeigt, nach VolLabel kopieren. Dabei halt aufpassen, dass Du einmal wahrscheinlich einen C-String (0 am Ende) und das andere mal einen Pascal-String hast (16 Bit Wert für Stringlänge am Anfang?). Wie auch immer, mit dem Debugger nachschauen, dann müsstest Du drauf kommen, wie Du es machen musst.

Sorry, wenn ich aufm Schlauch steh, aber mit Adressen und Pointern kann ich eigentlich gut umgehen (deswegen programmiere ich auch C/C++ und kein Pascal ). ;D

Pascal ist bei mir an die 15 Jahre her...
 
Das GetMem(toc, 2048 ) vor {Wie gehts hier weiter?} muss weg, das macht doch schon FUNCTION GetVTOC.
Da haste recht. Ich hatte übersehn, dass das FreeMem in der Funktion GetVTOC nur ausgeführt wird, wenn der Interrupt fehlschlägt.

Schau doch einfach mal mit dem Debugger in den Bereich, auf den der Pointer zeigt.
Werd ich tun.

Was ist VolLabel für ein Typ? Array of char oder string?
Ist bisher ein Array of Char (allerdings bin ich dazu "gezwungen" worden, weil eine Funktion keinen String sondern ein Array of Char wollte).

Sorry, wenn ich aufm Schlauch steh, aber mit Adressen und Pointern kann ich eigentlich gut umgehen (deswegen programmiere ich auch C/C++ und kein Pascal ). ;D
Es gibt eben Leute, die können gut mit Zeigern umgehn und solche wie mich, die es nicht können. ;)
Ich muss C/++ gezwungenermaßen im Studium programmieren (hoffentlich nicht mehr lange). Ich finds einfach eine hässliche Sprache.

Pascal ist bei mir an die 15 Jahre her...
Bei mir ist das auch schon ewig her, aber da ich hauptsächlich Delphi programmiere ...
Ich brauch das Programm für eine Boot-CD, die nunmal DOS bootet.

Ich meld mich wieder, wenn ich nicht weiterkomme oder weiß, wie's geht ;D

MfG Dalai


EDIT: Sorry, ich komm nicht weiter.
Wenn ich
Code:
Regs. BX := Seg(res);
benutze, bleibt die Kiste gnadenlos hängen (hängt sich auf), und wenn ich stattdessen (wie oben schon angedeutet)
Code:
Regs. ES := Seg(res);
verwende, dann schlägt der Ruf des Interrupt fehl (fCarry ist 1, das Carry Flag ist also gesetzt).
 
Zuletzt bearbeitet:
Moment mal:
Code:
CD-ROM - READ VTOC
AX = 1505h
ES:BX -> 2048-byte buffer
CX = drive number (0=A:)
DX = sector index (0=first volume descriptor,1=second,...)
Return:CF set on error
AX = error code (15=invalid drive,21=not ready)
CF clear if successful
AX = volume descriptor type (1=standard,FFh=terminator,0=other)

ES ist immer das Segment und ein Allzweckregister der Offset!

Es muss also heissen:
Regs. [B]ES := Seg[/B](res);
Regs. [B]BX := Ofs[/B](res);

Ja, C/C++ ist eine hässliche Sprache. Aber sie hat sich durchgesetzt und ist für alle möglichen Systeme, Prozessoren und Controllern verfügbar.
Delphi ist bestimmt ne schöne Entwicklungsumgebung, aber nichts für mich. Müsste ständig zwischen zwei Sprachen hin- und herspringen, da ich für PC und diverse µController entwickle. Ausserdem möchte ich die µC Komponenten auf dem PC testen können...
Nun, damals im Studium und auch privat hat mir Turbo-Pascal schon Spass gemacht.
 
Code:
ES ist immer das Segment und ein Allzweckregister der Offset!

Es muss also heissen:
Regs. [B]ES := Seg[/B](res);
Regs. [B]BX := Ofs[/B](res);
Irgendwas stimmt da immernoch nicht. Er bricht jetzt beim nachfolgenden FreeMem() mit einer "ungültigen Zeigeroperation" ab, das fCarry ist also wieder ungleich Null. Zusätzlich wird die lokale Variable Drive von 15 auf 32 geändert (soll/darf das sein?).

Ja, C/C++ ist eine hässliche Sprache.
Na wenigstens sind wir uns da einig ;D

Aber sie hat sich durchgesetzt und ist für alle möglichen Systeme, Prozessoren und Controllern verfügbar.
Das ist der große Vorteil. Ich sag ja nicht, dass man C/++ abschaffen soll (obwohl das auch ne Lösung wär *duck*), aber ich will kein C/++ programmieren, wenn es nicht sein muss.

MfG Dalai
 
Irgendwas stimmt da immernoch nicht. Er bricht jetzt beim nachfolgenden FreeMem() mit einer "ungültigen Zeigeroperation" ab, das fCarry ist also wieder ungleich Null. Zusätzlich wird die lokale Variable Drive von 15 auf 32 geändert (soll/darf das sein?).
Da scheint der Pointer nicht mehr zu stimmen.
Wenn sich eine lokale Variable wie von Geisterhand ändert, scheint jemand auf dem Stack rumzuferkeln.
Weiss jetzt auch nicht, was da los ist, kann gerade nicht überblicken, was Du jetzt für einen Code hast.
Wäre das ganze in C, könnte ich auch besser helfen. Ein Turbo-Pascal hätte ich zwar noch, aber meine damals schlauen Bücher dazu sind im Keller vergraben.
Wie war das noch mal bei den Pointern in Pascal? *Aus dem Gehirn rauskram*.
Da fehlt wohl eine Kleinigkeit bei der Pointerübergabe bei Dir.
Siehst Du den Unterschied?

Regs. ES := Seg(res^);
Regs. BX := Ofs(res^);


PS: Wieso muss man bei FreeMem() die Grösse angeben? Das ist doch Unfug.

PS: Hab sogar noch ein Zipfile mit nem kompletten TP5.5 auf meinem Rechner, darin auch einige Sourcen, auch mit ähnlichen Interrupt Calls. Das p^ sollte stimmen. Nachdem ich ein paar Sourcen überflogen hab, muss ich mein Urteil über die Schönheit von Programmiersprachen revidieren:
Pascal ist ja noch hässlicher als C/C++! Und umständlich obendrein!
Hatte das gar nicht so in Erinnerung.
Ist wohl nicht umsonst die Lernsprache für das Grundstudium - Programmieren, fast wie man spricht: Für Anfänger halt.;D
 
Zuletzt bearbeitet:
Da scheint der Pointer nicht mehr zu stimmen.
Wenn sich eine lokale Variable wie von Geisterhand ändert, scheint jemand auf dem Stack rumzuferkeln.
Weiss jetzt auch nicht, was da los ist, kann gerade nicht überblicken, was Du jetzt für einen Code hast.
Wäre das ganze in C, könnte ich auch besser helfen. Ein Turbo-Pascal hätte ich zwar noch, aber meine damals schlauen Bücher dazu sind im Keller vergraben.
Wie war das noch mal bei den Pointern in Pascal? *Aus dem Gehirn rauskram*.
Da fehlt wohl eine Kleinigkeit bei der Pointerübergabe bei Dir.
Siehst Du den Unterschied?

Regs. ES := Seg(res^);
Regs. BX := Ofs(res^);
So gehts besser (die lokalen Variablen ändern sich nicht mehr).
Allerdings hab ich grad in der Pascal-Hilfe gesehn, dass fCarry eine Konstante ist.
Das wird also nix mit einer if-Bedingung mit fCarry.
Ich werd mir mal das Flags des Records Reigsters anschauen, evtl ist damit eher was anzufangen.

PS: Wieso muss man bei FreeMem() die Grösse angeben? Das ist doch Unfug.
Nein, das ist im Pascal korrekt, der braucht 2 Parameter in dieser Funktion. Im Delphi braucht man die Größe nicht mehr.

MfG Dalai
 
Allerdings hab ich grad in der Pascal-Hilfe gesehn, dass fCarry eine Konstante ist.
Das wird also nix mit einer if-Bedingung mit fCarry.
MfG Dalai
Das widerspricht sich doch nicht.
Du kannst es natürlich abfragen, du kannst dem fCarry nur keinen Wert zuweisen.
Und es ist keine Konstante im eigentlichen Sinne, sondern ein Read-Only Flag!
Je nach Erfolg eines Interrupt-Calls wird es FALSE oder TRUE sein, sonst wäre das ganze sinnlos.

Hier wäre ein FUNCTION fCarry : CONST BOOLEAN angebracht, um das syntaktisch korrekt zu machen, aber sowas gibt es in Pascal glaub ich nicht (oder steckt genau das dahinter?).
In C ginge es jedenfalls so:
const bool fCarry(void)
{ return Flags.fCarry; }

*suspect* Wie lange programmierst Du?
 
Zuletzt bearbeitet:
Das widerspricht sich doch nicht.
Du kannst es natürlich abfragen, du kannst dem fCarry nur keinen Wert zuweisen.
Und es ist keine Konstante im eigentlichen Sinne, sondern ein Read-Only Flag!
Je nach Erfolg eines Interrupt-Calls wird es FALSE oder TRUE sein, sonst wäre das ganze sinnlos.
Da sich der Wert dieser Variable nicht geändert hat in den 'überwachten Ausdrücken' gehe ich davon aus, dass eine Abfrage eben sinnlos ist. Aber evtl lieg ich da falsch, kann ja sein.

*suspect* Wie lange programmierst Du?
Ich programmiere seit *schätz* 7-8 Jahren, aber mit Registern und Assembler (das isses ja fast) hatte ich - wie oben schon geschrieben - nie richtig was zu tun. Und Zeiger hab ich immer gemieden, wo es ging oder besser gesagt, meide ich immernoch.

BTW: Ich hab ggf eine Lösung:
Code:
if (Regs.Flags AND fCarry <>0) then
begin
  {und so weiter}
end;
scheint es zu tun. Nun muss ich noch rausbekommen, wie man den Kram in einen String bzw. das Array of Char bekommt...

MfG Dalai
 
Code:
if (Regs.Flags AND fCarry <>0) then
begin
  {und so weiter}
end;
Ja, dieses Konstrukt hab ich gerade auch gesehen, in einem alten Code. Das müsste funktionieren. Das mit dem fCarry ist wahrscheinlich eine der trickreichen borlandischen Erweiterungen der Turbos gegenüber Standard Pascal.
 
Mmh, so ganz sicher bin ich mir nicht damit:
Code:
var toc: Pointer;
     Drv: array[0..2047] of char;
begin    
    for Drive:= 'A' to 'Z' do
    begin
        {wenn das Laufwerk gültig und ein CD-ROM ist....}
        if (IsDriveValid(DriveToByte(Drive)) AND IsCDROM(DriveToByte(Drive))) then
        begin
            {...prüfen, ob Laufwerk bereit und gleichzeitig den Datenträgernamen auslesen}
            toc:= GetVTOC(DriveToByte(Drive));
            if toc <> nil then
            begin
                Move(toc^, Drv, 2048);
                Move(Drv[40], DriveLabel, 20);
                writeln(DriveLabel);[B] {das gibt zumindest schonmal eine Bezeichnung aus}[/B]
                FreeMem(toc, 2048);
            end;
        end;
    end;
end.

Kann man das einfacher gestalten? Ist das überhaupt richtig?

Ach übrigens hab ich festgestellt, dass GetVTOC beim ersten Aufruf nach dem Einlegen einer CD immer fehlzuschlagen scheint. Ich hab deshalb die Funktion ein bisschen geändert:
Code:
FUNCTION GetVTOC (DRIVE: BYTE): Pointer;
CONST
  CDROM_INTERRUPT = $2f;
VAR
  Regs : REGISTERS;
  res: Pointer;
[B]  i: integer;[/B]

BEGIN
  GetMem(res, 2048);

[B]  for i:= 1 to 2 do
  begin[/B]
    Regs. AX := $1505;
    Regs. CX := DRIVE-1;
    Regs. DX := 0;

    Regs. ES := Seg(res^);
    Regs. BX := Ofs(res^);

    Intr (CDROM_INTERRUPT, Regs);
  [B]end;[/B]

  if (Regs.Flags AND fCarry <> 0) Then
  begin
    FreeMem(res, 2048);
    GetVTOC := nil;
  end
  else
    GetVTOC := res;
END;

Damit scheint jetzt ein Aufruf von GetVTOC() zu genügen. Oder hat das ggf. Nebenwirkungen, wenn man das mehrfach ausführt?

MfG Dalai
 
Zuletzt bearbeitet:
Geht nicht auch sowas?
Code:
var toc: Pointer;
     Drv: array[0..19] of char;
begin    
     {...}
            if toc <> nil then
            begin
                Move(toc^ + 41, DriveLabel, 20);
                FreeMem(toc, 2048);
            end;
     {...}
Ich kann Pascal nicht wirklich - nicht hauen, wenn es kompletter Humbug ist.
 
Geht nicht auch sowas?
Code:
var toc: Pointer;
     Drv: array[0..19] of char;
begin    
     {...}
            if toc <> nil then
            begin
                Move(toc^ + 41, DriveLabel, 20);
                FreeMem(toc, 2048);
            end;
     {...}
nope, so einfach mit Adressen rumrechnen is nich.

Ich kann Pascal nicht wirklich - nicht hauen, wenn es kompletter Humbug ist.
Hier wird keiner gehauen ;D
Ein Fourm ist schließlich zum Fragen da.

MfG Dalai
 
So, ich hab in den letzten Tagen daraus ein IMO ganz brauchbares Programm gemacht.
Ich bin mal so frei und stelle die entscheidenden Teile hier rein, vor allem als Dank an alle Helfenden. Ggf. ist einiges davon noch nicht optimal, aber ich für meinen Teil lerne gerne dazu.

Code:
[B]Die Funktionen DriveToByte, IsCDROM und IsDriveValid sind unverändert; siehe erstes Posting.[/B]

var
  Drive                               : char;
  VolumeLabel, DriveLabel   : array[0..31] of char;
  [B]{Ein Record zum Speichern des ToC, ist später einfacher zu benutzen}[/B]
  VTOC                      : record
                                   X1                        : array[1..8] of byte;
                                   SystemID             : array[9..40] of char;
                                   VolumeID              : array[41..72] of char;
                                   X2                        : array[73..79] of byte;
                                   NumberOfSectors  : array[80..87] of byte;
                                   X3                        : array[88..119] of char;
                                   VolumeSetSize     : array[120..123] of char;
                                   VolumeSequence   : array[124..127] of char;
                                   SectorSize            : array[128..131] of char;
                                   PathTableLength    : array[132..139] of char;
                                   X4                         : array[140..189] of char;
                                   VolumeSetID         : array[190..318] of char;
                                   PublisherID           : array[319..446] Of Char;
                                   PreparerID             : array[447..574] Of Char;
                                   ApplicationID         : array[575..702] Of Char;
                                   CopyrightID           : array[703..739] Of Char;
                                   AbstractID            : array[740..776] Of Char;
                                   BibliographicID      : array[777..813] Of Char;
                                   CreationDate        : array[814..830] Of Char;
                                   ModificationDate   : array[831..847] Of Char;
                                   ExpirationDate      : array[848..864] Of Char;
                                   EffectiveDate        : array[865..880] Of Char;
                                   X5                       : array[881..882] of byte;
                                   ApplicationUse     : array[883..1394] of char;
                                   X6                       : array[1395..2048] Of Byte;
                              end;


FUNCTION GetVTOC (DRIVE: BYTE; num: integer): Pointer;
{ Drive => Laufwerk, dessen VTOC ausgelesen werden soll (1=A, 2=B, ...)
  num   => Volume Descriptor auslesen (0=erster, 1=zweiter, ...)
 }
CONST
  CDROM_INTERRUPT = $2F;
VAR
  Regs : REGISTERS;
  res  : Pointer;
  i    : integer;

BEGIN
  GetMem(res, 2048);

  for i:= 1 to 2 do
  begin
    Regs.AX := $1505;
    Regs.CX := DRIVE - 1;
    Regs.DX := num;

    Regs.ES := Seg(res^);
    Regs.BX := Ofs(res^);

    Intr(CDROM_INTERRUPT, Regs);
  end;

  if (Regs.Flags AND fCarry <> 0) then
  begin
    FreeMem(res, 2048);
    GetVTOC := nil;
  end
  else
    GetVTOC := res;
END;


FUNCTION GetVolDescriptor(var volname: array of char; num: integer): boolean;
var toc       : pointer;
    vol_name  : array[0..31] of char;
    i         : integer;
begin
  GetVolDescriptor:= false;
  toc:= GetVTOC(DriveToByte(Drive), num);
  if toc <> nil then
  begin
    Move(toc^, VTOC, SizeOf(VTOC));
    StrPCopy(vol_name, VTOC.VolumeID);

    FreeMem(toc, SizeOf(VTOC));
    GetVolDescriptor:= true;

    {Leerzeichen am Ende des "Strings" wegschnippeln}
    for i:= SizeOf(vol_name) - 1 downto 0 do
    begin
      if vol_name[i] <> ' ' then
        break
      else
        vol_name[i]:= #0;
    end;
    for i:= 0 to SizeOf(vol_name) do
      volname[i]:= vol_name[i];
  end;
end;


{***** Hauptprogramm ******}
begin
  if ParamCount > 0 then
  begin
    DriveErrorlevel:= 0;
    {übergebenen Parameter als zu suchende LW-Bezeichnung annehmen}
    StrPCopy(VolumeLabel, ParamStr(1));

    for Drive:= 'A' to 'Z' do
    begin
      {wenn das Laufwerk gültig und ein CD-ROM ist....}
      if (IsDriveValid(DriveToByte(Drive)) AND IsCDROM(DriveToByte(Drive))) then
      begin
        {...prüfen, ob Laufwerk bereit und gleichzeitig den Datenträgernamen auslesen}
        if GetVolDescriptor(DriveLabel, 0) then
        begin
          [B]{Hier kann man dann machen was man will mit der ausgelesenen Bezeichnung}[/B]
        end;
      end;
    end;
  end;
end.


Nachdem ich ein paar Sourcen überflogen hab, muss ich mein Urteil über die Schönheit von Programmiersprachen revidieren:
Pascal ist ja noch hässlicher als C/C++! Und umständlich obendrein!
Das kommt aber ganz auf die Anforderungen an! Bei C/++ gibts mit Sicherheit Sachen, die mehr Aufwand benötigen als im Pascal. Aber wir wollen das ja nicht schon wieder in ein Thema C/++ gegen Pascal/Delphi ausarten lassen. Jede Sprache hat ihre Berechtigung.

Ist wohl nicht umsonst die Lernsprache für das Grundstudium - Programmieren, fast wie man spricht: Für Anfänger halt.
Im Studium Pascal? Ist bei uns nicht so. Hier wird ausschließlich C, dann ab 2. Semester nur noch C++ gelehrt, im 3. kommt noch Java dazu.
Für Anfänger ist Pascal aber trotzdem nicht, Delphi schon gar nicht. Ich möchte nur daran erinnern, dass auch durchaus ernstzunehmende Programme mit Delphi programmiert sind! Zu nennen wären da z.B. Total Commander, The Bat!, Spybot Search & Destroy, Motherboard Monitor und Skype (sind nur einige).


So, und jetzt betrachte ich mein Problem als gelöst. Wenn trotzdem noch jemand seinen Senf dazugeben will, kann er das gern tun ;D . Auch Hinweise auf evtl. Probleme im o.g. Code sind willkommen.
Achso: Natürlich möchte ich denen danken, die mir geholfen haben! Danke!

MfG Dalai


EDIT: Ich hab doch noch was vergessen: Falls jemand das Programm braucht (es gibt davon auch eine 32 Bit Windows-Variante), einfach Bescheid sagen! Das Programm findet den Laufwerksbuchstaben zu einer per Parameter übergebenen Datenträgerbezeichnung einer CD/DVD und gibt einen entsprechenden Errorlevel zurück. Also wunderbar geeignet, um CDs/DVDs zu suchen oder besser gesagt zu finden (in Batch-Skripten).
 
Zuletzt bearbeitet:
Glückwunsch, dass das jetzt geklappt hat.

Ich hatte zu CP/M-Zeiten vor dem Studium mit Turbo-Pascal angefangen. C unter CP/M konnte man vergessen, denn die Compiler waren miserabel und sterbenslangsam.
Die ersten zwei Semester dann Pascal unter Unix und DOS. Das war ab 1988 und C-Programmierer wurden händeringend von den Firmen gesucht.
In der Firma, in der ich vor und während der ersten Semester war, mussten wir uns entscheiden, welche Programmiersprache wir für ein x86 Embedded-Projekt verwenden wollen (wir alle hatten Z80-ASM und Pascal Erfahrungen). Wir entschieden uns für TopSpeed Modula II mit Pascal-Syntax, sinnvollen Erweiterungen für modulare Konzepte, Co-Routinen als Ansatz für parallele Datenverarbeitung, hardwarenahe Programmierung wie in C möglich.
Das auf Pascal aufbauende Modula II, später Modula III und danach Oberon bieten eigentlich genau das, wonach die Lehre des Software Engineering immer schreit.
Breitflächig durchgesetzt hat sich paradoxerweise ein Scherz namens C und später halt C++. Meine Modula II Zeit hat auch nicht lange gedauert, es ging kein Weg an C vorbei.
Meinen Zugang zu C bekam ich mit einem Buch namens "Von Modula II zu C und zurück".
Alles, was in C möglich ist, geht auch in Modula II, umgekehrt nicht ganz. Aber irgendwie hat mir C dann immer mehr Spass gemacht und der damals vorherrschende Coolness-Faktor für C hatte mich auch gepackt.
Seit Ende des Studiums bin ich nicht mehr in die Verlegenheit gekommen, irgendwas Pascal artiges zu nutzen. C, C++ und Java sind eben angesagt. Alles Sprachen, welche man auch im Embedded Bereich einsetzen kann.
 
Zurück
Oben Unten