Click here to Skip to main content
15,894,180 members
Articles / Programming Languages / C#

C Sharp Ripper

Rate me:
Please Sign up or sign in to vote.
4.89/5 (58 votes)
13 Jan 20045 min read 448.9K   9.7K   214  
C# code to handle CDROM drives and read CD tracks
//
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER 
//  REMAINS UNCHANGED.
//
//  Email:  yetiicb@hotmail.com
//
//  Copyright (C) 2002-2003 Idael Cardoso. 
//

using System;
using System.Runtime.InteropServices;


namespace Ripper
{
  /// <summary>
  /// Wrapper class for Win32 functions and structures needed to handle CD.
  /// </summary>
  internal class Win32Functions
  {
    public enum DriveTypes:uint 
    {
      DRIVE_UNKNOWN = 0,
      DRIVE_NO_ROOT_DIR,
      DRIVE_REMOVABLE,
      DRIVE_FIXED,
      DRIVE_REMOTE,
      DRIVE_CDROM,
      DRIVE_RAMDISK
    };
    
    [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
    public extern static DriveTypes GetDriveType(string drive);

    //DesiredAccess values
    public const uint GENERIC_READ      = 0x80000000;
    public const uint GENERIC_WRITE     = 0x40000000;
    public const uint GENERIC_EXECUTE   = 0x20000000;
    public const uint GENERIC_ALL       = 0x10000000;

    //Share constants
    public const uint FILE_SHARE_READ   = 0x00000001;  
    public const uint FILE_SHARE_WRITE  = 0x00000002;  
    public const uint FILE_SHARE_DELETE = 0x00000004;  
    
    //CreationDisposition constants
    public const uint CREATE_NEW        = 1;
    public const uint CREATE_ALWAYS     = 2;
    public const uint OPEN_EXISTING     = 3;
    public const uint OPEN_ALWAYS       = 4;
    public const uint TRUNCATE_EXISTING = 5;

    /// <summary>
    /// Win32 CreateFile function, look for complete information at Platform SDK
    /// </summary>
    /// <param name="FileName">In order to read CD data FileName must be "\\.\\D:" where D is the CDROM drive letter</param>
    /// <param name="DesiredAccess">Must be GENERIC_READ for CDROMs others access flags are not important in this case</param>
    /// <param name="ShareMode">O means exlusive access, FILE_SHARE_READ allow open the CDROM</param>
    /// <param name="lpSecurityAttributes">See Platform SDK documentation for details. NULL pointer could be enough</param>
    /// <param name="CreationDisposition">Must be OPEN_EXISTING for CDROM drives</param>
    /// <param name="dwFlagsAndAttributes">0 in fine for this case</param>
    /// <param name="hTemplateFile">NULL handle in this case</param>
    /// <returns>INVALID_HANDLE_VALUE on error or the handle to file if success</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static IntPtr CreateFile(string FileName, uint DesiredAccess, 
      uint ShareMode, IntPtr lpSecurityAttributes, 
      uint CreationDisposition, uint dwFlagsAndAttributes,
      IntPtr hTemplateFile);

    /// <summary>
    /// The CloseHandle function closes an open object handle.
    /// </summary>
    /// <param name="hObject">Handle to an open object.</param>
    /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static int CloseHandle(IntPtr hObject);

    public const uint IOCTL_CDROM_READ_TOC         = 0x00024000;
    public const uint IOCTL_STORAGE_CHECK_VERIFY   = 0x002D4800;
    public const uint IOCTL_CDROM_RAW_READ         = 0x0002403E;
    public const uint IOCTL_STORAGE_MEDIA_REMOVAL  = 0x002D4804;
    public const uint IOCTL_STORAGE_EJECT_MEDIA    = 0x002D4808;
    public const uint IOCTL_STORAGE_LOAD_MEDIA     = 0x002D480C;

    /// <summary>
    /// Most general form of DeviceIoControl Win32 function
    /// </summary>
    /// <param name="hDevice">Handle of device opened with CreateFile, <see cref="Ripper.Win32Functions.CreateFile"/></param>
    /// <param name="IoControlCode">Code of DeviceIoControl operation</param>
    /// <param name="lpInBuffer">Pointer to a buffer that contains the data required to perform the operation.</param>
    /// <param name="InBufferSize">Size of the buffer pointed to by lpInBuffer, in bytes.</param>
    /// <param name="lpOutBuffer">Pointer to a buffer that receives the operation's output data.</param>
    /// <param name="nOutBufferSize">Size of the buffer pointed to by lpOutBuffer, in bytes.</param>
    /// <param name="lpBytesReturned">Receives the size, in bytes, of the data stored into the buffer pointed to by lpOutBuffer. </param>
    /// <param name="lpOverlapped">Pointer to an OVERLAPPED structure. Discarded for this case</param>
    /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static int DeviceIoControl(IntPtr hDevice, uint IoControlCode, 
      IntPtr lpInBuffer, uint InBufferSize,
      IntPtr lpOutBuffer, uint nOutBufferSize,
      ref uint lpBytesReturned,
      IntPtr lpOverlapped);

    [ StructLayout( LayoutKind.Sequential )]
    public struct TRACK_DATA 
    {
      public  byte  Reserved;
      private byte  BitMapped;
      public  byte  Control 
      { 
        get
        {
          return (byte)(BitMapped & 0x0F);
        }
        set
        {
          BitMapped = (byte)((BitMapped & 0xF0) | (value & (byte)0x0F));
        }
      }
      public byte Adr
      {
        get
        {
          return (byte)((BitMapped & (byte)0xF0) >> 4);
        }
        set
        {
          BitMapped = (byte)((BitMapped & (byte)0x0F) | (value << 4));
        }
      }
      public byte  TrackNumber;
      public byte  Reserved1;
      /// <summary>
      /// Don't use array to avoid array creation
      /// </summary>
      public byte  Address_0;
      public byte  Address_1;
      public byte  Address_2;
      public byte  Address_3;
    };

    public const int MAXIMUM_NUMBER_TRACKS = 100;

    [ StructLayout( LayoutKind.Sequential )]
    public class TrackDataList
    {
      [MarshalAs(UnmanagedType.ByValArray, SizeConst=MAXIMUM_NUMBER_TRACKS*8)]
      private byte[] Data;
      public TRACK_DATA this [int Index]
      {
        get
        {
          if ( (Index < 0) | (Index >= MAXIMUM_NUMBER_TRACKS))
          {
            throw new IndexOutOfRangeException();
          }
          TRACK_DATA res;
          GCHandle handle = GCHandle.Alloc(Data, GCHandleType.Pinned);
          try
          {
            IntPtr buffer = handle.AddrOfPinnedObject();
            buffer = (IntPtr)(buffer.ToInt32() + (Index*Marshal.SizeOf(typeof(TRACK_DATA))));
            res = (TRACK_DATA)Marshal.PtrToStructure(buffer, typeof(TRACK_DATA));
          }
          finally
          {
            handle.Free();
          }
          return res;
        }
      }
      public TrackDataList()
      {
        Data = new byte[MAXIMUM_NUMBER_TRACKS*Marshal.SizeOf(typeof(TRACK_DATA))];
      }
    }
    
    [StructLayout( LayoutKind.Sequential )]
    public class CDROM_TOC 
    {
      public ushort Length;
      public byte FirstTrack = 0;
      public byte LastTrack = 0;
      
      public TrackDataList TrackData;

      public CDROM_TOC()
      {
        TrackData = new TrackDataList();
        Length = (ushort)Marshal.SizeOf(this);
      }
    } 
 
    [ StructLayout( LayoutKind.Sequential )]
    public class PREVENT_MEDIA_REMOVAL 
    {
      public byte PreventMediaRemoval = 0;
    }
    
    public enum TRACK_MODE_TYPE { YellowMode2, XAForm2, CDDA }
    [ StructLayout( LayoutKind.Sequential )]
      public class RAW_READ_INFO 
    {
      public long  DiskOffset = 0;
      public uint  SectorCount = 0;
      public TRACK_MODE_TYPE  TrackMode = TRACK_MODE_TYPE.CDDA;
    }
    
    /// <summary>
    /// Overload version of DeviceIOControl to read the TOC (Table of contents)
    /// </summary>
    /// <param name="hDevice">Handle of device opened with CreateFile, <see cref="Ripper.Win32Functions.CreateFile"/></param>
    /// <param name="IoControlCode">Must be IOCTL_CDROM_READ_TOC for this overload version</param>
    /// <param name="InBuffer">Must be <code>IntPtr.Zero</code> for this overload version </param>
    /// <param name="InBufferSize">Must be 0 for this overload version</param>
    /// <param name="OutTOC">TOC object that receive the CDROM TOC</param>
    /// <param name="OutBufferSize">Must be <code>(UInt32)Marshal.SizeOf(CDROM_TOC)</code> for this overload version</param>
    /// <param name="BytesReturned">Receives the size, in bytes, of the data stored into OutTOC</param>
    /// <param name="Overlapped">Pointer to an OVERLAPPED structure. Discarded for this case</param>
    /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static int DeviceIoControl(IntPtr hDevice, uint IoControlCode, 
      IntPtr InBuffer, uint InBufferSize,
      [Out] CDROM_TOC OutTOC, uint OutBufferSize,
      ref uint BytesReturned,
      IntPtr Overlapped);

    /// <summary>
    /// Overload version of DeviceIOControl to lock/unlock the CD
    /// </summary>
    /// <param name="hDevice">Handle of device opened with CreateFile, <see cref="Ripper.Win32Functions.CreateFile"/></param>
    /// <param name="IoControlCode">Must be IOCTL_STORAGE_MEDIA_REMOVAL for this overload version</param>
    /// <param name="InMediaRemoval">Set the lock/unlock state</param>
    /// <param name="InBufferSize">Must be <code>(UInt32)Marshal.SizeOf(PREVENT_MEDIA_REMOVAL)</code> for this overload version</param>
    /// <param name="OutBuffer">Must be <code>IntPtr.Zero</code> for this overload version </param>
    /// <param name="OutBufferSize">Must be 0 for this overload version</param>
    /// <param name="BytesReturned">A "dummy" varible in this case</param>
    /// <param name="Overlapped">Pointer to an OVERLAPPED structure. Discarded for this case</param>
    /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static int DeviceIoControl(IntPtr hDevice, uint IoControlCode, 
      [In] PREVENT_MEDIA_REMOVAL InMediaRemoval, uint InBufferSize,
      IntPtr OutBuffer, uint OutBufferSize,
      ref uint BytesReturned,
      IntPtr Overlapped);

    /// <summary>
    /// Overload version of DeviceIOControl to read digital data
    /// </summary>
    /// <param name="hDevice">Handle of device opened with CreateFile, <see cref="Ripper.Win32Functions.CreateFile"</param>
    /// <param name="IoControlCode">Must be IOCTL_CDROM_RAW_READ for this overload version</param>
    /// <param name="rri">RAW_READ_INFO structure</param>
    /// <param name="InBufferSize">Size of RAW_READ_INFO structure</param>
    /// <param name="OutBuffer">Buffer that will receive the data to be read</param>
    /// <param name="OutBufferSize">Size of the buffer</param>
    /// <param name="BytesReturned">Receives the size, in bytes, of the data stored into OutBuffer</param>
    /// <param name="Overlapped">Pointer to an OVERLAPPED structure. Discarded for this case</param>
    /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
    [System.Runtime.InteropServices.DllImport("Kernel32.dll", SetLastError=true)]
    public extern static int DeviceIoControl(IntPtr hDevice, uint IoControlCode, 
      [In] RAW_READ_INFO rri, uint InBufferSize,
      [In, Out] byte[] OutBuffer, uint OutBufferSize,
      ref uint BytesReturned,
      IntPtr Overlapped);
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions