private void CheckError(UInt32 code)
        {
            switch (code)
            {
            case 1102:                          // ERROR_BEGINNING_OF_MEDIA
                beginningMediaDetected = true;
                break;

            case 1100:                          // ERROR_END_OF_MEDIA
                endMediaDetected = true;
                break;

            case 1103:                          // ERROR_SETMARK_DETECTED
                setMarkDetected = true;
                break;

            case 1101:                          // ERROR_FILEMARK_DETECTED
                fileMarkDetected = true;
                break;

            case 1104:                          // ERROR_NO_DATA_DETECTED
                endOfDataDetected = true;
                break;

            case 19:                                    // ERROR_WRITE_PROTECT
                throw(new WriteProtectedException());

            default:
                TapeDriveFunctions.CheckGeneralError(code);
                break;
            }
        }
        //////////////////////////////////////////////

        /// <summary>
        /// Constructs a tape drive with the given integer ID.
        /// All tape drives under windows have an ID, starting at 0.
        /// </summary>
        /// <param name="tapeID">ID of tape</param>
        public TapeDrive(int tapeID)
        {
            // check OS version first
            if (Environment.OSVersion.Platform != PlatformID.Win32NT)
            {
                throw(new PlatformNotSupportedException("Tape drive access requires WindowsNT 4 or higher"));
            }

            tapeHandle = TapeDriveFunctions.CreateFile(@"\\.\TAPE" + tapeID,
                                                       0x80000000 | 0x40000000, // (GENERIC_READ | GENERIC_WRITE) read/write access
                                                       0,                       // not used
                                                       null,                    // not used
                                                       3,                       // (OPEN_EXISTING) required for tape devices
                                                       0,                       // not used
                                                       0);                      // not used

            if (tapeHandle == 0)
            {
                throw(new TapeDriveNotFoundException());
            }

            info = TapeDriveFunctions.GetTapeDriveParameters(this);

            setInfo.Compression        = info.Compression;
            setInfo.DataPadding        = info.DataPadding;
            setInfo.ECC                = info.ECC;
            setInfo.EOTWarningZoneSize = info.EOTWarningZoneSize;
            setInfo.ReportSetmarks     = info.ReportSetmarks;

            tapeStream = new TapeStream(this);
        }
        /// <summary>
        /// Seeks to a specified position within the stream
        /// </summary>
        /// <param name="offset">offset from SeekOrigin to seek to</param>
        /// <param name="seekTo">where seeking should begin</param>
        /// <returns>new stream position</returns>
        public override long Seek(long offset, SeekOrigin seekTo)
        {
            long position = 0;

            switch (seekTo)
            {
            case SeekOrigin.Begin:
                position = offset;
                break;

            case SeekOrigin.Current:
                position = Position + offset;
                break;

            case SeekOrigin.End:
                position = Length + offset;
                break;
            }

            UInt32 lowBits, highBits;

            lowBits  = (UInt32)position;
            highBits = (UInt32)(position >> 32);

            CheckError(TapeDriveFunctions.SetTapePosition(tapeDrive.Handle, 0, 0, lowBits, highBits, false));

            return(position);
        }
        /// <summary>
        /// Writes data to the tapedrive
        /// </summary>
        /// <param name="buffer">byte buffer to copy from</param>
        /// <param name="offset">integer offset within buffer to start copying data from</param>
        /// <param name="count">number of bytes to copy</param>
        public override void Write(byte[] buffer, int offset, int count)
        {
            UInt32 bytesWritten;

            byte[] buffer2 = new byte[count];

            Array.Copy(buffer, offset, buffer2, 0, count);

            TapeDriveFunctions.WriteFile(tapeDrive.Handle, buffer2, (UInt32)count, out bytesWritten, null);
        }
 /// <summary>
 /// Closes connection to the tape drive
 /// </summary>
 public void Close()
 {
     if (tapeHandle != 0)
     {
         if (Loaded)
         {
             UnLoad();
         }
         TapeDriveFunctions.CloseHandle(tapeHandle);
         tapeHandle = 0;
     }
 }
        /// <summary>
        /// Reads data from the tapedrive
        /// </summary>
        /// <param name="buffer">byte buffer to copy into</param>
        /// <param name="offset">integer offset within buffer to start copying data to</param>
        /// <param name="count">number of bytes to copy</param>
        /// <returns>number of bytes read</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            UInt32 bytesRead;

            byte[] buffer2 = new byte[count];

            TapeDriveFunctions.ReadFile(tapeDrive.Handle, buffer2, (UInt32)count, out bytesRead, null);

            Array.Copy(buffer2, 0, buffer, offset, (int)bytesRead);

            return((int)bytesRead);
        }
        private void CheckError(UInt32 code)
        {
            switch (code)
            {
            case 1105:                          // ERROR_PARTITION_FAILURE
                throw(new TapeDriveException("Format failed: Tape could not be partitioned"));

            case 1108:                          // ERROR_UNABLE_TO_LOCK_MEDIA
                throw(new LockFailedException());

            case 1109:                          // ERROR_UNABLE_TO_UNLOAD_MEDIA
                break;

            default:
                TapeDriveFunctions.CheckGeneralError(code);
                break;
            }
        }
 /// <summary>
 /// Used by all Format() functions to call CreateTapePartition()
 /// </summary>
 /// <param name="option">Win32 option to send</param>
 /// <param name="count"></param>
 /// <param name="size"></param>
 private void FormatHelper(FormatOption option, UInt32 count, UInt32 size)
 {
     CheckError(TapeDriveFunctions.CreateTapePartition(tapeHandle, (UInt32)option, count, size));
 }
 /// <summary>
 /// Called by all functions that require PrepareTape()
 /// </summary>
 /// <param name="option">PrepareType option</param>
 /// <param name="immediate">If true, return immediately.
 /// If false, return after operation has finished</param>
 private void Prepare(PrepareOption option, bool immediate)
 {
     CheckError(TapeDriveFunctions.PrepareTape(tapeHandle, (UInt32)option, immediate));
 }
 /// <summary>
 /// Writes an end of data mark at the current position
 /// </summary>
 public void WriteEndOfDataMark()
 {
     CheckError(TapeDriveFunctions.EraseTape(tapeDrive.Handle, 0, false));
 }
 /// <summary>
 /// Writes the specified number of set marks to the current position
 /// </summary>
 /// <param name="count">Number of set marks to write</param>
 public void WriteSetMark(uint count)
 {
     CheckError(TapeDriveFunctions.WriteTapemark(tapeDrive.Handle, 0, count, false));
 }
 /// <summary>
 /// Erases the tape from the current position to the end of partition.
 /// </summary>
 public void Erase()
 {
     CheckError(TapeDriveFunctions.EraseTape(tapeDrive.Handle, 1, false));
 }
 /// <summary>
 /// Flushes buffers to the drive
 /// </summary>
 public override void Flush()
 {
     TapeDriveFunctions.FlushFileBuffers(tapeDrive.Handle);
 }