/* * Tape handling functions * * Copyright 1999 Chris Morgan <cmorgan@wpi.edu> * James Abbatiello <abbeyj@wpi.edu> * Copyright 2006 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include <stdarg.h> #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" #include "winbase.h" #include "winerror.h" #include "winioctl.h" #include "ddk/ntddtape.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(tape); static DWORD set_error_from_status( NTSTATUS status ) { DWORD error = RtlNtStatusToDosError( status ); SetLastError( error ); return error; } /************************************************************************ * BackupRead (KERNEL32.@) * * Backup a file or directory. */ BOOL WINAPI BackupRead( HANDLE file, LPBYTE buffer, DWORD to_read, LPDWORD read, BOOL abort, BOOL security, LPVOID *context ) { FIXME( "(%p, %p, %d, %p, %d, %d, %p)\n", file, buffer, to_read, read, abort, security, context ); SetLastError( ERROR_NOT_SUPPORTED ); return FALSE; } /************************************************************************ * BackupSeek (KERNEL32.@) * * Seek forward in a backup stream. */ BOOL WINAPI BackupSeek( HANDLE file, DWORD seek_low, DWORD seek_high, LPDWORD seeked_low, LPDWORD seeked_high, LPVOID *context ) { FIXME( "(%p, %d, %d, %p, %p, %p)\n", file, seek_low, seek_high, seeked_low, seeked_high, context ); SetLastError( ERROR_NOT_SUPPORTED ); return FALSE; } /************************************************************************ * BackupWrite (KERNEL32.@) * * Restore a file or directory. */ BOOL WINAPI BackupWrite( HANDLE file, LPBYTE buffer, DWORD to_write, LPDWORD written, BOOL abort, BOOL security, LPVOID *context ) { FIXME( "(%p, %p, %d, %p, %d, %d, %p)\n", file, buffer, to_write, written, abort, security, context ); SetLastError( ERROR_NOT_SUPPORTED ); return FALSE; } /************************************************************************ * CreateTapePartition (KERNEL32.@) * * Format a tape. */ DWORD WINAPI CreateTapePartition( HANDLE device, DWORD method, DWORD count, DWORD size ) { NTSTATUS status; TAPE_CREATE_PARTITION part; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %d, %d)\n", device, method, count, size ); part.Method = method; part.Count = count; part.Size = size; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_CREATE_PARTITION, &part, sizeof(TAPE_CREATE_PARTITION), NULL, 0 ); return set_error_from_status( status ); } /************************************************************************ * EraseTape (KERNEL32.@) * * Erase a tape. */ DWORD WINAPI EraseTape( HANDLE device, DWORD type, BOOL immediate ) { NTSTATUS status; TAPE_ERASE erase; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %d)\n", device, type, immediate ); erase.Type = type; erase.Immediate = immediate; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_ERASE, &erase, sizeof(TAPE_ERASE), NULL, 0 ); return set_error_from_status( status ); } /************************************************************************ * GetTapeParameters (KERNEL32.@) * * Retrieve information about a tape or tape drive. */ DWORD WINAPI GetTapeParameters( HANDLE device, DWORD operation, LPDWORD size, LPVOID info ) { NTSTATUS status = STATUS_INVALID_PARAMETER; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %p, %p)\n", device, operation, size, info ); switch (operation) { case GET_TAPE_DRIVE_INFORMATION: status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_GET_DRIVE_PARAMS, NULL, 0, info, *size ); break; case GET_TAPE_MEDIA_INFORMATION: status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_GET_MEDIA_PARAMS, NULL, 0, info, *size ); break; default: ERR( "Unhandled operation: 0x%08x\n", operation ); } return set_error_from_status( status ); } /************************************************************************ * GetTapePosition (KERNEL32.@) * * Retrieve the current tape position. */ DWORD WINAPI GetTapePosition( HANDLE device, DWORD type, LPDWORD partition, LPDWORD offset_low, LPDWORD offset_high ) { NTSTATUS status; TAPE_GET_POSITION in, out; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %p, %p, %p)\n", device, type, partition, offset_low, offset_high ); memset( &in, 0, sizeof(TAPE_GET_POSITION) ); in.Type = type; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_GET_POSITION, &in, sizeof(TAPE_GET_POSITION), &out, sizeof(TAPE_GET_POSITION) ); if (status != STATUS_SUCCESS) return set_error_from_status( status ); *partition = out.Partition; *offset_low = out.OffsetLow; *offset_high = out.OffsetHigh; return set_error_from_status( status ); } /************************************************************************ * GetTapeStatus (KERNEL32.@) * * Determine if the tape device is ready for operation. */ DWORD WINAPI GetTapeStatus( HANDLE device ) { NTSTATUS status; IO_STATUS_BLOCK io; TRACE( "(%p)\n", device ); status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_GET_STATUS, NULL, 0, NULL, 0 ); return set_error_from_status( status ); } /************************************************************************ * PrepareTape (KERNEL32.@) * * Prepare a tape for operation. */ DWORD WINAPI PrepareTape( HANDLE device, DWORD operation, BOOL immediate ) { NTSTATUS status; TAPE_PREPARE prep; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %d)\n", device, operation, immediate ); prep.Operation = operation; prep.Immediate = immediate; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_PREPARE, &prep, sizeof(TAPE_PREPARE), NULL, 0 ); return set_error_from_status( status ); } /************************************************************************ * SetTapeParameters (KERNEL32.@) * * Configure a tape or tape device. */ DWORD WINAPI SetTapeParameters( HANDLE device, DWORD operation, LPVOID info ) { NTSTATUS status = STATUS_INVALID_PARAMETER; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %p)\n", device, operation, info ); switch (operation) { case SET_TAPE_DRIVE_INFORMATION: status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_SET_DRIVE_PARAMS, info, sizeof(TAPE_SET_DRIVE_PARAMETERS), NULL, 0 ); break; case SET_TAPE_MEDIA_INFORMATION: status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_SET_MEDIA_PARAMS, info, sizeof(TAPE_SET_MEDIA_PARAMETERS), NULL, 0 ); break; default: ERR( "Unhandled operation: 0x%08x\n", operation ); } return set_error_from_status( status ); } /************************************************************************ * SetTapePosition (KERNEL32.@) * * Set the tape position on a given device. */ DWORD WINAPI SetTapePosition( HANDLE device, DWORD method, DWORD partition, DWORD offset_low, DWORD offset_high, BOOL immediate ) { NTSTATUS status; TAPE_SET_POSITION pos; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %d, %d, %d, %d)\n", device, method, partition, offset_low, offset_high, immediate ); pos.Method = method; pos.Partition = partition; pos.Offset.u.LowPart = offset_low; pos.Offset.u.HighPart = offset_high; pos.Immediate = immediate; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_SET_POSITION, &pos, sizeof(TAPE_SET_POSITION), NULL, 0 ); return set_error_from_status( status ); } /************************************************************************ * WriteTapemark (KERNEL32.@) * * Write tapemarks on a tape. */ DWORD WINAPI WriteTapemark( HANDLE device, DWORD type, DWORD count, BOOL immediate ) { NTSTATUS status; TAPE_WRITE_MARKS marks; IO_STATUS_BLOCK io; TRACE( "(%p, %d, %d, %d)\n", device, type, count, immediate ); marks.Type = type; marks.Count = count; marks.Immediate = immediate; status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, IOCTL_TAPE_WRITE_MARKS, &marks, sizeof(TAPE_WRITE_MARKS), NULL, 0 ); return set_error_from_status( status ); }