/* #FN# Allows selecting a cassette image using FileDialog window */ void /* #AS# Nothing */ CTapeDlg:: OnBrowse() { if( PickFileName( TRUE, m_szTapeFile, IDS_SELECT_CAS_LOAD, IDS_FILTER_CAS, "cas", PF_LOAD_FLAGS, TRUE, DEFAULT_TAP, this ) && *m_szTapeFile != '\0' ) { SetDlgItemText( IDC_TAPE_FILE, m_szTapeFile ); /* Open a tape image */ PrepareTape( m_szTapeFile, FALSE ); SetDlgState(); } } /* #OF# CTapeDlg::OnBrowse */
/* #FN# Called when the user clicks the CANCEL button */ void /* #AS# Nothing */ CTapeDlg:: OnCancel() { /* Restore the original tape */ if( _stricmp( m_szTapeFile, m_szTapeBack ) != 0 ) { if( !PrepareTape( m_szTapeBack, TRUE, TRUE ) ) m_nCurrentBack = 1; } /* Restore the pointer to a current block */ cassette_current_block = m_nCurrentBack; CCommonDlg::OnCancel(); } /* #OF# CTapeDlg::OnCancel */
BOOL EjectTape( VOID ){ printf( "Attempting to Eject Tape...\n" ) ; if(gb_Tape_Handle != NULL) { if( PrepareTape( gb_Tape_Handle, TAPE_UNLOAD, 0 ) ) { DisplayDriverError( GetLastError( ) ) ; return TEST_ERROR ; } else { return SUCCESS ; } } }
/* #FN# Called when the user clicks the OK button */ void /* #AS# Nothing */ CTapeDlg:: OnOK() { char szTapeOld[ FILENAME_MAX ]; /* There is a problem with messages routing when the dialog is closed with Enter/Alt-O key. KILLFOCUS message arrives to late and we have to invoke KillFocus handlers in OnOK method by ourselves. That's why we use this member. */ m_bExitPass = TRUE; /* We have to indicate the 'last minute' changes */ strcpy( szTapeOld, m_szTapeFile ); /* Unfortunately, edit controls do not lose the focus before handling this when the user uses accelerators */ ReceiveFocused(); if( _stricmp( m_szTapeFile, m_szTapeBack ) != 0 || _stricmp( szTapeOld, m_szTapeFile ) != 0 || /* The tape position was changed, so reattach the tape to allow reading it */ m_nCurrentBack != cassette_current_block ) { int nCurrentBlock = cassette_current_block; /* Always reattach the selected tape */ PrepareTape( m_szTapeFile ); /* Restore a tape position */ cassette_current_block = nCurrentBlock; if( _stricmp( m_szTapeFile, m_szTapeBack ) != 0 ) { /* Update the registry */ WriteRegString( NULL, REG_FILE_TAPE, m_szTapeFile ); } } CCommonDlg::OnOK(); } /* #OF# CTapeDlg::OnOK */
/* #FN# The framework calls this function before an edit losing input focus */ void /* #AS# Nothing */ CTapeDlg:: OnKillfocusFile() { char szTapeOld[ FILENAME_MAX ]; strcpy( szTapeOld, m_szTapeFile ); GetDlgItemText( IDC_TAPE_FILE, m_szTapeFile, FILENAME_MAX - 1 ); if( !m_bExitPass && _stricmp( szTapeOld, m_szTapeFile ) != 0 ) { /* Open a tape image */ PrepareTape( m_szTapeFile ); /* Set the dialog controls */ SetDlgState(); } } /* #OF# CTapeDlg::OnKillfocusFile */
/* #FN# Displays New Tape Image dialog box */ void /* #AS# Nothing */ CTapeDlg:: OnNewImage() { CNewTapeImageDlg dlgNewTapeImage; if( IDOK == dlgNewTapeImage.DoModal() && /* Attach tape image to the tape recorder if it was expected */ dlgNewTapeImage.m_bAttachTape ) { /* Set a name of the created image */ _strncpy( m_szTapeFile, dlgNewTapeImage.m_szTapeName, FILENAME_MAX - 1 ); SetDlgItemText( IDC_TAPE_FILE, m_szTapeFile ); /* Open a tape image */ PrepareTape( m_szTapeFile, FALSE, TRUE ); SetDlgState(); } } /* #OF# CTapeDlg::OnNewImage */
static int w32_internal_mtop ( HANDLE hFile, U32* pStat, struct mtop* mtop, ifd_t ifd ) { int rc = 0; ASSERT( pStat && mtop ); // (sanity check) // General technique: do the i/o, save results, update the // device status (based on the results), then check results... switch ( mtop->mt_op ) { case MTLOAD: // (load media) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = PrepareTape( hFile, TAPE_LOAD, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTUNLOAD: // (unload media) case MTOFFL: // (make media offline (same as unload)) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = PrepareTape( hFile, TAPE_UNLOAD, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTSEEK: // (position media) { do { errno = SetTapePosition( hFile, TAPE_LOGICAL_BLOCK, 0, mtop->mt_count, 0, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTREW: // (rewind) { if ( 1 != mtop->mt_count ) { errno = EINVAL; rc = -1; } else { do { errno = SetTapePosition( hFile, TAPE_REWIND, 0, 0, 0, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTFSF: // (FORWARD space FILE) case MTBSF: // (BACKWARD space FILE) { if ( !mtop->mt_count ) { errno = EINVAL; rc = -1; } else { LARGE_INTEGER liCount; liCount.QuadPart = mtop->mt_count; if ( MTBSF == mtop->mt_op ) liCount.QuadPart = -liCount.QuadPart; // (negative == backwards) do { errno = SetTapePosition( hFile, TAPE_SPACE_FILEMARKS, 0, liCount.LowPart, liCount.HighPart, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTFSR: // (FORWARD space BLOCK) case MTBSR: // (BACKWARD space BLOCK) { if ( !mtop->mt_count ) { errno = EINVAL; rc = -1; } else { LARGE_INTEGER liCount; liCount.QuadPart = mtop->mt_count; if ( MTBSR == mtop->mt_op ) liCount.QuadPart = -liCount.QuadPart; // (negative == backwards) do { errno = SetTapePosition( hFile, TAPE_SPACE_RELATIVE_BLOCKS, 0, liCount.LowPart, liCount.HighPart, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTSETBLK: // (set blocksize) { TAPE_SET_MEDIA_PARAMETERS media_parms; media_parms.BlockSize = mtop->mt_count; do { errno = SetTapeParameters( hFile, SET_TAPE_MEDIA_INFORMATION, &media_parms ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTEOTWARN: // (set EOT Warning Zone size in bytes) { TAPE_SET_DRIVE_PARAMETERS set_drive_parms; set_drive_parms.ECC = g_drive_parms[ifd].ECC; set_drive_parms.Compression = g_drive_parms[ifd].Compression; set_drive_parms.DataPadding = g_drive_parms[ifd].DataPadding; set_drive_parms.ReportSetmarks = g_drive_parms[ifd].ReportSetmarks; set_drive_parms.EOTWarningZoneSize = mtop->mt_count; do { errno = SetTapeParameters( hFile, SET_TAPE_DRIVE_INFORMATION, &set_drive_parms ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } break; case MTWEOF: // (write TAPEMARK) { if ( mtop->mt_count < 0 ) { errno = EINVAL; rc = -1; } else { // PROGRAMMING NOTE: We prefer "long" filemarks over any other type // because, according to the SDK documentaion: // // "A short filemark contains a short erase gap that cannot be // overwritten unless the write operation is performed from the // beginning of the partition or from an earlier long filemark." // // "A long filemark contains a long erase gap that allows an // application to position the tape at the beginning of the filemark // and to overwrite the filemark and the erase gap." // // Thus if TAPE_LONG_FILEMARKS is not supported we try ONLY the generic // TAPE_FILEMARKS variety and return an error if that fails; we do NOT // ever attempt the TAPE_SHORT_FILEMARKS or TAPE_SETMARKS variety. DWORD dwTapemarkType = TAPE_LONG_FILEMARKS; if ( !( g_drive_parms[ifd].FeaturesHigh & TAPE_DRIVE_WRITE_LONG_FMKS ) ) dwTapemarkType = TAPE_FILEMARKS; do { errno = WriteTapemark( hFile, dwTapemarkType, mtop->mt_count, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTERASE: // (write erase gap or erase entire tape (data security erase)) { if (1 && 0 != mtop->mt_count // (0 == write erase gap at current position) && 1 != mtop->mt_count // (1 == erases the remainder of entire tape) ) { errno = EINVAL; rc = -1; } else { DWORD dwEraseType = mtop->mt_count ? TAPE_ERASE_LONG : TAPE_ERASE_SHORT; do { errno = EraseTape( hFile, dwEraseType, FALSE ); errno = w32_internal_rc ( pStat ); } while ( EINTR == errno ); } } break; case MTNOP: // (no operation) { errno = 0; rc = 0; } break; default: // (invalid/unsupported tape operation) { errno = EINVAL; rc = -1; } break; } return (rc = (0 == errno || ENOSPC == errno) ? 0 : /* errno != 0 && errno != ENOSPC */ -1); }
int win32_tape_device::tape_op(struct mtop *mt_com) { DWORD result = NO_ERROR; int index; if (m_fd < 3 || m_fd >= (int)(NUMBER_HANDLE_ENTRIES + 3) || TapeHandleTable[m_fd - 3].OSHandle == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } PTAPE_HANDLE_INFO pHandleInfo = &TapeHandleTable[m_fd - 3]; switch (mt_com->mt_op) { case MTRESET: case MTNOP: case MTSETDRVBUFFER: break; case MTRAS1: case MTRAS2: case MTRAS3: case MTSETDENSITY: errno = ENOTTY; result = (DWORD)-1; break; case MTFSF: for (index = 0; index < mt_com->mt_count; index++) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE); if (result == NO_ERROR) { pHandleInfo->ulFile++; pHandleInfo->bEOF = true; pHandleInfo->bEOT = false; } } break; case MTBSF: for (index = 0; index < mt_com->mt_count; index++) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE); if (result == NO_ERROR) { pHandleInfo->ulFile--; pHandleInfo->bBlockValid = false; pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } } break; case MTFSR: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_RELATIVE_BLOCKS, 0, mt_com->mt_count, 0, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } else if (result == ERROR_FILEMARK_DETECTED) { pHandleInfo->bEOF = true; } break; case MTBSR: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_RELATIVE_BLOCKS, 0, -mt_com->mt_count, ~0, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } else if (result == ERROR_FILEMARK_DETECTED) { pHandleInfo->ulFile--; pHandleInfo->bBlockValid = false; pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } break; case MTWEOF: result = WriteTapemark(pHandleInfo->OSHandle, TAPE_FILEMARKS, mt_com->mt_count, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOF = true; pHandleInfo->bEOT = false; pHandleInfo->ulFile += mt_com->mt_count; pHandleInfo->bBlockValid = true; pHandleInfo->ullFileStart = 0; } break; case MTREW: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_REWIND, 0, 0, 0, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; pHandleInfo->ulFile = 0; pHandleInfo->bBlockValid = true; pHandleInfo->ullFileStart = 0; } break; case MTOFFL: result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOAD, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; pHandleInfo->ulFile = 0; pHandleInfo->ullFileStart = 0; } break; case MTRETEN: result = PrepareTape(pHandleInfo->OSHandle, TAPE_TENSION, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; pHandleInfo->ulFile = 0; pHandleInfo->bBlockValid = true; pHandleInfo->ullFileStart = 0; } break; case MTBSFM: for (index = 0; index < mt_com->mt_count; index++) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE); if (result == NO_ERROR) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE); pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } } break; case MTFSFM: for (index = 0; index < mt_com->mt_count; index++) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, mt_com->mt_count, 0, FALSE); if (result == NO_ERROR) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, (DWORD)-1, ~0, FALSE); pHandleInfo->bEOD = false; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; } } break; case MTEOM: while (1) { result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_FILEMARKS, 0, 1, 0, FALSE); if (result != NO_ERROR) { pHandleInfo->bEOF = false; if (result == ERROR_END_OF_MEDIA) { pHandleInfo->bEOD = true; pHandleInfo->bEOT = true; return 0; } if (result == ERROR_NO_DATA_DETECTED) { pHandleInfo->bEOD = true; pHandleInfo->bEOT = false; return 0; } break; } else { pHandleInfo->bEOF = true; pHandleInfo->ulFile++; } } break; case MTERASE: result = EraseTape(pHandleInfo->OSHandle, TAPE_ERASE_LONG, FALSE); if (result == NO_ERROR) { pHandleInfo->bEOD = true; pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; pHandleInfo->ulFile = 0; pHandleInfo->bBlockValid = true; pHandleInfo->ullFileStart = 0; } break; case MTSETBLK: { TAPE_SET_MEDIA_PARAMETERS SetMediaParameters; SetMediaParameters.BlockSize = mt_com->mt_count; result = SetTapeParameters(pHandleInfo->OSHandle, SET_TAPE_MEDIA_INFORMATION, &SetMediaParameters); break; } case MTSEEK: { TAPE_POSITION_INFO TapePositionInfo; result = SetTapePosition(pHandleInfo->OSHandle, TAPE_ABSOLUTE_BLOCK, 0, mt_com->mt_count, 0, FALSE); memset(&TapePositionInfo, 0, sizeof(TapePositionInfo)); DWORD dwPosResult = GetTapePositionInfo(pHandleInfo->OSHandle, &TapePositionInfo); if (dwPosResult == NO_ERROR && TapePositionInfo.FileSetValid) { pHandleInfo->ulFile = (ULONG)TapePositionInfo.FileNumber; } else { pHandleInfo->ulFile = ~0U; } break; } case MTTELL: { DWORD partition; DWORD offset; DWORD offsetHi; result = GetTapePosition(pHandleInfo->OSHandle, TAPE_ABSOLUTE_BLOCK, &partition, &offset, &offsetHi); if (result == NO_ERROR) { return offset; } break; } case MTFSS: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_SETMARKS, 0, mt_com->mt_count, 0, FALSE); break; case MTBSS: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_SPACE_SETMARKS, 0, -mt_com->mt_count, ~0, FALSE); break; case MTWSM: result = WriteTapemark(pHandleInfo->OSHandle, TAPE_SETMARKS, mt_com->mt_count, FALSE); break; case MTLOCK: result = PrepareTape(pHandleInfo->OSHandle, TAPE_LOCK, FALSE); break; case MTUNLOCK: result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOCK, FALSE); break; case MTLOAD: result = PrepareTape(pHandleInfo->OSHandle, TAPE_LOAD, FALSE); break; case MTUNLOAD: result = PrepareTape(pHandleInfo->OSHandle, TAPE_UNLOAD, FALSE); break; case MTCOMPRESSION: { TAPE_GET_DRIVE_PARAMETERS GetDriveParameters; TAPE_SET_DRIVE_PARAMETERS SetDriveParameters; DWORD size; size = sizeof(GetDriveParameters); result = GetTapeParameters(pHandleInfo->OSHandle, GET_TAPE_DRIVE_INFORMATION, &size, &GetDriveParameters); if (result == NO_ERROR) { SetDriveParameters.ECC = GetDriveParameters.ECC; SetDriveParameters.Compression = (BOOLEAN)mt_com->mt_count; SetDriveParameters.DataPadding = GetDriveParameters.DataPadding; SetDriveParameters.ReportSetmarks = GetDriveParameters.ReportSetmarks; SetDriveParameters.EOTWarningZoneSize = GetDriveParameters.EOTWarningZoneSize; result = SetTapeParameters(pHandleInfo->OSHandle, SET_TAPE_DRIVE_INFORMATION, &SetDriveParameters); } break; } case MTSETPART: result = SetTapePosition(pHandleInfo->OSHandle, TAPE_LOGICAL_BLOCK, mt_com->mt_count, 0, 0, FALSE); break; case MTMKPART: if (mt_com->mt_count == 0) { result = CreateTapePartition(pHandleInfo->OSHandle, TAPE_INITIATOR_PARTITIONS, 1, 0); } else { result = CreateTapePartition(pHandleInfo->OSHandle, TAPE_INITIATOR_PARTITIONS, 2, mt_com->mt_count); } break; default: errno = ENOTTY; result = (DWORD)-1; break; } if ((result == NO_ERROR && pHandleInfo->bEOF) || (result == ERROR_FILEMARK_DETECTED && mt_com->mt_op == MTFSR)) { TAPE_POSITION_INFO TapePositionInfo; if (GetTapePositionInfo(pHandleInfo->OSHandle, &TapePositionInfo) == NO_ERROR) { pHandleInfo->bBlockValid = true; pHandleInfo->ullFileStart = TapePositionInfo.BlockNumber; } } switch (result) { case NO_ERROR: case (DWORD)-1: /* Error has already been translated into errno */ break; case ERROR_FILEMARK_DETECTED: errno = EIO; break; case ERROR_END_OF_MEDIA: pHandleInfo->bEOT = true; errno = EIO; break; case ERROR_NO_DATA_DETECTED: pHandleInfo->bEOD = true; errno = EIO; break; case ERROR_NO_MEDIA_IN_DRIVE: pHandleInfo->bEOF = false; pHandleInfo->bEOT = false; pHandleInfo->bEOD = false; errno = ENOMEDIUM; break; case ERROR_INVALID_HANDLE: case ERROR_ACCESS_DENIED: case ERROR_LOCK_VIOLATION: errno = EBADF; break; default: errno = EIO; break; } return result == NO_ERROR ? 0 : -1; }