Avatar
www.fr-an.de

Medieninformationen

Table of Content (IOCTL)

IOCTL_CDROM_READ_TOC control code

Mit dem IOCTL_CDROM_READ_TOC control code kann man die Vorgehensweise aus Table of Content (MMC) vereinfachen. Man benötigt keinen Command Descriptor Block und muss die Antwort nicht auswerten sondern erhält sofort eine aufbereitete Struktur. Ausserdem benötigt man keine Schreibrechte für die Laufwerke. Der IOCTL_CDROM_READ_TOC control code ist in der Headerdatei Ntddcdrm.h definert. Diese findet sich nicht im MSDN sondern im DDK. Am besten bemüht man eine Internetsuchmaschine und findet zum Beispiel hier:

 
  #define IOCTL_CDROM_READ_TOC
             CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
        

Die Function CTL_CODE ist zum Beispiel bei OSR Online erläutert. Die Konstanten finden sich in der Ntddcdrm.h und der devioctl.h (Zum Beispiel hier).

 
  #define IOCTL_CDROM_BASE          FILE_DEVICE_CD_ROM
 
  #define FILE_DEVICE_CD_ROM        0x00000002
 
  #define FILE_READ_ACCESS          ( 0x0001 )
 
  #define METHOD_BUFFERED           0
        

Daraus ergibt sich dann in Delphi folgendes:

 
  const
    FILE_DEVICE_CD_ROM = $00000002;
    IOCTL_CDROM_BASE   = FILE_DEVICE_CD_ROM;
    FILE_READ_ACCESS   = $0001;
    METHOD_BUFFERED    = 0;
 
  const
    IOCTL_CDROM_READ_TOC = (IOCTL_CDROM_BASE shl 16) or
                           (FILE_READ_ACCESS shl 14) or
                           ($0000 shl 2) or
                           METHOD_BUFFERED;
        
 

Antwortstruktur

Als Antwort erhält man eine CDROM_TOC Struktur, welche die TRACK_DATA Struktur enthält:

 
  typedef struct _CDROM_TOC {
    UCHAR      Length[2];
    UCHAR      FirstTrack;
    UCHAR      LastTrack;
    TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
  } CDROM_TOC, *PCDROM_TOC;
 
  typedef struct _TRACK_DATA {
    UCHAR Reserved;
    UCHAR Control  :4;
    UCHAR Adr  :4;
    UCHAR TrackNumber;
    UCHAR Reserved1;
    UCHAR Address[4];
  } TRACK_DATA, *PTRACK_DATA;
        

Die Constante MAXIMUM_NUMBER_TRACKS findet sich in der ntddcdrm.h:

 
  #define MAXIMUM_NUMBER_TRACKS 100
        

Daraus ergibt sich eine ähnliche Struktur wie bereits in Table of Content (MMC). Sie unterscheidet darin, dass hier die Trackdata in einem statischen Array enthalten sind sowie Control und Adr als Halbbytes definiert sind, was es in Delphi nicht gibt. In Delphi ergibt sich:

 
  const
    MAXIMUM_NUMBER_TRACKS = 100;
 
  type
    TAddress = Array[0..3] of Byte;
 
  type
    TTRACK_DATA = record
      Reserved        : Byte;
      Adr_and_Control : Byte;
      TrackNumber     : Byte;
      Reserved1       : Byte;
      Address         : TAddress;
    end;
    PTRACK_DATA = ^TTRACK_DATA;
 
  type
    TCDROM_TOC = record
      Length     : Word;
      FirstTrack : Byte;
      LastTrack  : Byte;
      TrackData  : Array[1..MAXIMUM_NUMBER_TRACKS] of TTRACK_DATA;
    end;
    PCDROM_TOC = ^TCDROM_TOC;
        

Erläuterungen zu den Variablen findet man bei MSDN nicht. Da die Werte die selben sind wie bei der Verwendung der MMC sollten sie auch die selbe Bedeutung besitzen.

 

Ausführung

Die Ausführung reduziert sich auf:

 
    ...
 
  begin
 
    ...
 
    {
    *  Handle holen.
    }
    dwDesiredAccess := GENERIC_READ;
    dwShareMode     := FILE_SHARE_READ;
    aDevice         := CreateFile(PAnsiChar(Format('\\.\%s:', [aDrive])),
                                  dwDesiredAccess, dwShareMode,
                                  nil, OPEN_EXISTING, 0, 0);
    {
    *  TOC initialisieren.
    }
    FillChar(TOC, SizeOf(TOC), $00);
    {
    *  Befehl ausführen.
    }
    DeviceIoControl(aDevice, IOCTL_CDROM_READ_TOC, nil, 0, @TOC, SizeOf(TOC),
                    nReturned, nil);
    TOC.Length := TOC.Length and $00FF shl 8) or (TOC.Length and $FF00 shr 8)
 
    ...
 
  end;
        

Der Datentyp Word scheint in C und Delphi etwas unterschiedlich zu sein. Deshalb muss man die Bytes der Länge tauschen, da $1200 (4608) nicht das selbe ist wie $0012 (18).

Im Gegensatz zu Table of Content (MMC) führt die Ausführung von DeviceIoControl hier zu einem Fehler "Das Gerät ist nicht bereit" wenn kein Datenträger eingelegt ist.

 

Demo, welche diese Funktion nutzt:

Medien Disc TOC (IOCTL) (podDiscTOC(IOCTL).7z - 269 kb) MD5 (1 kb). Stand: 26. Februar 2012

Änderungen an der Demo

26.02.2012 -
Aktualisiert: Groupbox "Optische Laufwerke".

 

Fr_An - Erstellt: 18. Februar 2012 - Letzte Änderung: 26. Februar 2012

seit 28. Juli 2010