Sektorweises Auslesen einer CD



  • Guten Abend,

    kann man unter Windows Vista (64 bit) via CreateFileW + SetFilePointer + ReadFile auch eine Audio-CD sektorweise auslesen?

    Seltsamerweise funktioniert das nur mit einer anderen Methode. Deshalb meine Frage. 🙂



  • Soweit ich weiss geht das über eigene IOCTLs (DeviceIoControl), und nicht über ReadFile.

    Wieso?



  • DeviceIoControl ist die andere Methode. Die funktioniert nach wie vor perfekt. Die Frage war aber ob ReadFile bei einer Audio-CD auch funktioniert.

    SetFilePointer funktioniert zwar, aber ReadFile liefert indirekt (praktisch unabhängig von den CreateFileW-Parametern) ständig ERROR_HANDLE_EOF (C0000011) zurück. Da aber eine Audio-CD definitiv Daten bzw. Sektoren enthält (und SetFilePointer funktioniert), muß es sich offenbar um eine Macke des Betriebssystems handeln.

    Na fein (bzw. unfein), dann muß ich eben auch noch unter Windows Vista mit DeviceIoControl herumrödeln. 😞

    hustbaer schrieb:

    Wieso?

    CD-Recovery.



  • Ich kann die Sektoren einer CD ganz normal mit CreateFile(), SetFilePointer() und ReadFile() öffnen und lesen.
    Du mußt das Ganze natürlich als "Volume" bzw. "Floppy drive" öffnen, nicht als Datei o.ä.

    Siehe auch MSDN zu CreateFile() !

    Im Prinzip so (alle Fehlerabfragen entfernt!):

    #define NUI32_SIZEOF_CHAR_DISKSECTOR 512
    
    char c_Buffer[NUI32_SIZEOF_CHAR_DISKSECTOR];
    int64 i64_sector;      //Hier ist die Nummer der Sektor.
    LARGE_INTEGER large_integer_sector;
    
    large_integer_sector.QuadPart = ( 0x200 * i64_sector ) & ~( 0x200-1 );  //make sectors.
    _tcscpy( tcsz_drivename, TEXT( "\\\\.\\D:" ) );       //Drive name.
    h_drive = CreateFile( tcsz_drivename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                          NULL, OPEN_EXISTING, 0, NULL ); //Als "Volume" oder "Floppy drive" öffnen.
    if ( SetFilePointer( h_file_drive, large_integer_sector.LowPart,
                         &large_integer_sector.HighPart, FILE_BEGIN ) != INVALID_SET_FILE_POINTER )
                                                          //Pointer an Anfang setzen.
    {
      if ( ReadFile( h_file_drive, c_Buffer, ui32_sectorSize, &dword_read, NULL ) != FALSE )
                                                          //Den gewünschten Sektor einlesen.
      {
        if ( dword_read == ui32_sectorSize )              //Überprüfe ob auch die richtige Anzahl Bytes gelesen wurden.
        {
          ..
        }
    

    (Natürlich wird vorausgesetzt, Du hast die nötigen Admin-Rechte!)

    Achtung: beim SetFilePointer(): Den Teil "large_integer_sector.LowPart" als normalen Variablenwert, aber den Teil "&large_integer_sector.HighPart" als Pointer übergeben!!!

    HTH,
    Martin



  • So i.e. funktioniert es bei Daten-CDs (allerdings muß die Sektorgröße 2048 sein), nicht aber bei Audio-CDs.

    Wie gesagt, bei Audio-CDs liefert ReadFile indirekt ERROR_HANDLE_EOF (C0000011) zurück. Genauer gesagt, ReadFile gibt keinen Fehler zurück, liest aber nichts ein (dword_read wäre immer null).



  • @compactor:
    Ich wollte nicht wissen warum du die Audio-Daten auslesen willst, sondern warum du gerade über ReadFile lesen willst, wenn DeviceIoControl ja problemlos funktioniert.



  • In meiner Version der WinIoCtl.h steht folgender Kommentar:

    //
    // The following device control codes are common for all class drivers.  They
    // should be used in place of the older IOCTL_DISK, IOCTL_CDROM and IOCTL_TAPE
    // common codes
    //
    
    #define IOCTL_STORAGE_CHECK_VERIFY            CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
    #define IOCTL_STORAGE_CHECK_VERIFY2           CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)
    #define IOCTL_STORAGE_MEDIA_REMOVAL           CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)
    
    (...)
    

    Mit keinem von denen lassen sich Sektoren von einer Audio-CD direkt auslesen. DeviceIoControl funktioniert aber mit einem "older IOCTL_CDROM_xxx control code".

    Was soll denn jetzt unter Windows Vista genommen werden? Oder soll man unter Vista keine Sektoren mehr auslesen? 🙂



  • compactor schrieb:

    Was soll denn jetzt unter Windows Vista genommen werden? Oder soll man unter Vista keine Sektoren mehr auslesen? 🙂

    Öhm. Nimm einfach das was funktioniert 🙂

    Ich habe damals die IOCTL_CDROM Codes verwendet, aber das war auch für XP, und ich weiss nicht ob im SDK damals die IOCTL_STORAGE schon definiert waren.

    Vor allem würde ich nichts implementieren, was du nicht testen kannst. Falls du ein CDROM/OS/... auftreiben kannst, wo die IOCTL_STORAGE Codes funktionieren, kannst du ja beides implementieren, und denn dem User die Möglichkeit geben, auszuwählen, was verwendet werden soll (z.B. Options-Dialog mit den Einstellungen "AUTO", "CDROM" und "STORAGE").

    Aber wie gesagt: einfach so implementieren, ohne dass du es (erfolgreich) testen kannst, würde ich nicht.


Anmelden zum Antworten