From 8426256abb26c6cd426cba4a7d9fda8e10e77f33 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 4 Feb 2004 10:23:01 +0000 Subject: [PATCH] Add better DeviceIocontrol support. It still sucks, but sucks less. --- lib/Makefile.am | 4 +- lib/_cdio_win32.c | 140 ++++++------------------------- lib/_cdio_win32.h | 70 ++++++++++++++++ lib/win32ioctl.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 118 deletions(-) create mode 100644 lib/_cdio_win32.h create mode 100644 lib/win32ioctl.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 12ce975c..beaadbe0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.14 2004/02/02 03:56:46 rocky Exp $ +# $Id: Makefile.am,v 1.15 2004/02/04 10:23:01 rocky Exp $ # # Copyright (C) 2003 Rocky Bernstein # @@ -37,6 +37,7 @@ libcdio_sources = \ _cdio_stream.h \ _cdio_sunos.c \ _cdio_win32.c \ + _cdio_win32.h \ bytesex.h \ bytesex_asm.h \ cdio.c \ @@ -47,6 +48,7 @@ libcdio_sources = \ scsi_mmc.h \ sector.c \ util.c \ + win32ioctl.c wnaspi32.h lib_LTLIBRARIES = libcdio.la libiso9660.la diff --git a/lib/_cdio_win32.c b/lib/_cdio_win32.c index e7df1890..efdccd92 100644 --- a/lib/_cdio_win32.c +++ b/lib/_cdio_win32.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_win32.c,v 1.21 2004/02/02 03:55:19 rocky Exp $ + $Id: _cdio_win32.c,v 1.22 2004/02/04 10:23:01 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -26,13 +26,12 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_win32.c,v 1.21 2004/02/02 03:55:19 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_win32.c,v 1.22 2004/02/04 10:23:01 rocky Exp $"; #include #include #include #include "cdio_assert.h" -#include "cdio_private.h" #include "scsi_mmc.h" /* LBA = msf.frame + 75 * ( msf.second - 2 + 60 * msf.minute ) */ @@ -51,6 +50,7 @@ static const char _rcsid[] = "$Id: _cdio_win32.c,v 1.21 2004/02/02 03:55:19 rock #include #include +#include "_cdio_win32.h" #include #include @@ -132,32 +132,6 @@ typedef struct __RAW_READ_INFO { TRACK_MODE_TYPE TrackMode; } RAW_READ_INFO, *PRAW_READ_INFO; -#pragma pack() - -typedef struct { - lsn_t start_lsn; - UCHAR Control : 4; - UCHAR Format; -} track_info_t; - -typedef struct { - /* Things common to all drivers like this. - This must be first. */ - generic_img_private_t gen; - - HANDLE h_device_handle; /* device descriptor */ - long hASPI; - short i_sid; - long (*lpSendCommand)( void* ); - - /* Track information */ - bool toc_init; /* if true, info below is valid. */ - track_info_t tocent[100]; /* entry info for each track */ - track_t total_tracks; /* number of tracks in image */ - track_t first_track_num; /* track number of first track */ - -} _img_private_t; - /* General ioctl() CD-ROM command function */ static bool _cdio_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) @@ -174,43 +148,12 @@ _cdio_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) return(mci_error == 0); } -static const char * -cdio_winnt_is_cdrom(const char drive_letter) -{ - static char psz_win32_drive[7]; - static char root_path_name[8]; - _img_private_t obj; - - /* Initializations */ - obj.h_device_handle = NULL; - obj.i_sid = 0; - obj.hASPI = 0; - obj.lpSendCommand = 0; - - sprintf( psz_win32_drive, "\\\\.\\%c:", drive_letter ); - sprintf( root_path_name, "\\\\.\\%c:\\", drive_letter ); - - obj.h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, - FILE_FLAG_NO_BUFFERING | - FILE_FLAG_RANDOM_ACCESS, NULL ); - if (obj.h_device_handle != NULL - && (DRIVE_CDROM == GetDriveType(root_path_name))) { - CloseHandle(obj.h_device_handle); - return strdup(psz_win32_drive); - } else { - CloseHandle(obj.h_device_handle); - return NULL; - } -} - static const char * cdio_is_cdrom(const char drive_letter) { static char psz_win32_drive[7]; if ( WIN_NT ) { - return cdio_winnt_is_cdrom(drive_letter); + return win32ioctl_is_cdrom(drive_letter); } else { HMODULE hASPI = NULL; long (*lpGetSupport)( void ) = NULL; @@ -335,22 +278,7 @@ _cdio_init_win32 (void *user_data) _obj->lpSendCommand = 0; if ( WIN_NT ) { - char psz_win32_drive[7]; - unsigned int len=strlen(_obj->gen.source_name); - - cdio_debug("using winNT/2K/XP ioctl layer"); - - if (cdio_is_device_win32(_obj->gen.source_name)) { - sprintf( psz_win32_drive, "\\\\.\\%c:", _obj->gen.source_name[len-2] ); - - _obj->h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, - FILE_FLAG_NO_BUFFERING | - FILE_FLAG_RANDOM_ACCESS, NULL ); - return (_obj->h_device_handle == NULL) ? false : true; - } else - return false; + return win32ioctl_init_win32(_obj); } else { HMODULE hASPI = NULL; long (*lpGetSupport)( void ) = NULL; @@ -591,8 +519,13 @@ static int _cdio_read_audio_sectors (void *user_data, void *data, lsn_t lsn, unsigned int nblocks) { - return _cdio_mmc_read_sectors( user_data, data, lsn, - CDIO_MMC_READ_TYPE_CDDA, nblocks ); + _img_private_t *_obj = user_data; + if ( _obj->hASPI ) { + return _cdio_mmc_read_sectors( user_data, data, lsn, + CDIO_MMC_READ_TYPE_CDDA, nblocks ); + } else { + return win32ioctl_read_audio_sectors( _obj, data, lsn, nblocks ); + } } /*! @@ -605,7 +538,6 @@ _cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn, { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; _img_private_t *_obj = user_data; - int ret; if (_obj->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); @@ -622,44 +554,18 @@ _cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn, _obj->gen.ioctls_debugged++; if ( _obj->hASPI ) { + int ret; ret = _cdio_mmc_read_sectors(user_data, buf, lsn, CDIO_MMC_READ_TYPE_ANY, 1); + if( ret != 0 ) return ret; + if (mode2_form2) + memcpy (data, buf, M2RAW_SECTOR_SIZE); + else + memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); + return 0; } else { - DWORD dwBytesReturned; - RAW_READ_INFO cdrom_raw; - - /* Initialize CDROM_RAW_READ structure */ - cdrom_raw.DiskOffset.QuadPart = CDIO_CD_FRAMESIZE * lsn; - cdrom_raw.SectorCount = 1; - cdrom_raw.TrackMode = XAForm2; - - if( DeviceIoControl( _obj->h_device_handle, - IOCTL_CDROM_RAW_READ, &cdrom_raw, - sizeof(RAW_READ_INFO), buf, - sizeof(buf), &dwBytesReturned, NULL ) - == 0 ) { - /* Retry in Yellowmode2 */ - cdrom_raw.TrackMode = YellowMode2; - if( DeviceIoControl( _obj->h_device_handle, - IOCTL_CDROM_RAW_READ, &cdrom_raw, - sizeof(RAW_READ_INFO), buf, - sizeof(buf), &dwBytesReturned, NULL ) - == 0 ) { - cdio_info("Error reading %lu (%ld)\n", lsn, GetLastError()); - return 1; - } - } - ret = 0; + return win32ioctl_read_mode2_sector( _obj, data, lsn, mode2_form2 ); } - - if( ret != 0 ) return ret; - - if (mode2_form2) - memcpy (data, buf, M2RAW_SECTOR_SIZE); - else - memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - - return 0; } /*! @@ -923,10 +829,10 @@ _cdio_get_arg (void *user_data, const char key[]) if (!strcmp (key, "source")) { return _obj->gen.source_name; } else if (!strcmp (key, "access-mode")) { - if ( WIN_NT ) - return "winNT/2K/XP ioctl"; - else if (_obj->hASPI) + if (_obj->hASPI) return "ASPI"; + else if ( WIN_NT ) + return "winNT/2K/XP ioctl"; else return "undefined WIN32"; } diff --git a/lib/_cdio_win32.h b/lib/_cdio_win32.h new file mode 100644 index 00000000..9df87aeb --- /dev/null +++ b/lib/_cdio_win32.h @@ -0,0 +1,70 @@ +/* + $Id: _cdio_win32.h,v 1.1 2004/02/04 10:23:01 rocky Exp $ + + Copyright (C) 2004 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "cdio_private.h" + +#pragma pack() + +typedef struct { + lsn_t start_lsn; + UCHAR Control : 4; + UCHAR Format; +} track_info_t; + +typedef struct { + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; + + HANDLE h_device_handle; /* device descriptor */ + long hASPI; + short i_sid; + long (*lpSendCommand)( void* ); + + /* Track information */ + bool toc_init; /* if true, info below is valid. */ + track_info_t tocent[100]; /* entry info for each track */ + track_t total_tracks; /* number of tracks in image */ + track_t first_track_num; /* track number of first track */ + +} _img_private_t; + +/*! + Reads an audio device using the DeviceIoControl method into data + starting from lsn. Returns 0 if no error. + */ +int win32ioctl_read_audio_sectors (_img_private_t *obj, void *data, lsn_t lsn, + unsigned int nblocks); +/*! + Reads a single mode2 sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. + */ +int +win32ioctl_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn, + bool mode2_form2); + +const char *win32ioctl_is_cdrom(const char drive_letter); + +/*! + Initialize internal structures for CD device. + */ +bool win32ioctl_init_win32 (_img_private_t *env); + + diff --git a/lib/win32ioctl.c b/lib/win32ioctl.c new file mode 100644 index 00000000..5f980489 --- /dev/null +++ b/lib/win32ioctl.c @@ -0,0 +1,204 @@ +/* + $Id: win32ioctl.c,v 1.1 2004/02/04 10:23:01 rocky Exp $ + + Copyright (C) 2004 Rocky Bernstein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains Win32-specific code using the DeviceIoControl + access method. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: win32ioctl.c,v 1.1 2004/02/04 10:23:01 rocky Exp $"; + +#include +#include +#include "cdio_assert.h" + +#ifdef HAVE_WIN32_CDROM + +#include +#include + +#include +#include +#include + +#ifndef IOCTL_CDROM_BASE +# define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#endif +#ifndef IOCTL_CDROM_RAW_READ +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, \ + METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#endif + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct __RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +#include "_cdio_win32.h" + +const char * +win32ioctl_is_cdrom(const char drive_letter) +{ + static char psz_win32_drive[7]; + static char root_path_name[8]; + _img_private_t env; + + /* Initializations */ + env.h_device_handle = NULL; + env.i_sid = 0; + env.hASPI = 0; + env.lpSendCommand = 0; + + sprintf( psz_win32_drive, "\\\\.\\%c:", drive_letter ); + sprintf( root_path_name, "\\\\.\\%c:\\", drive_letter ); + + env.h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | + FILE_FLAG_RANDOM_ACCESS, NULL ); + if (env.h_device_handle != NULL + && (DRIVE_CDROM == GetDriveType(root_path_name))) { + CloseHandle(env.h_device_handle); + return strdup(psz_win32_drive); + } else { + CloseHandle(env.h_device_handle); + return NULL; + } +} + +/*! + Reads an audio device using the DeviceIoControl method into data + starting from lsn. Returns 0 if no error. + */ +int +win32ioctl_read_audio_sectors (_img_private_t *env, void *data, lsn_t lsn, + unsigned int nblocks) +{ + DWORD dwBytesReturned; + RAW_READ_INFO cdrom_raw; + + /* Initialize CDROM_RAW_READ structure */ + cdrom_raw.DiskOffset.QuadPart = CDIO_CD_FRAMESIZE_RAW * lsn; + cdrom_raw.SectorCount = nblocks; + cdrom_raw.TrackMode = CDDA; + + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_RAW_READ, &cdrom_raw, + sizeof(RAW_READ_INFO), data, + CDIO_CD_FRAMESIZE_RAW * nblocks, + &dwBytesReturned, NULL ) == 0 ) { + cdio_info("Error reading audio-mode %lu (%ld)\n", lsn, GetLastError()); + return 1; + } + return 0; +} + +/*! + Reads a single mode2 sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. + */ +int +win32ioctl_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn, + bool mode2_form2) +{ + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + DWORD dwBytesReturned; + RAW_READ_INFO cdrom_raw; + + /* Initialize CDROM_RAW_READ structure */ + cdrom_raw.DiskOffset.QuadPart = CDIO_CD_FRAMESIZE * lsn; + cdrom_raw.SectorCount = 1; + cdrom_raw.TrackMode = mode2_form2 ? XAForm2 : YellowMode2; + + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_RAW_READ, &cdrom_raw, + sizeof(RAW_READ_INFO), buf, + sizeof(buf), &dwBytesReturned, NULL ) + == 0 ) { + /* Retry in Yellowmode2 */ + if (mode2_form2) { + cdio_debug("Retrying mode2 request as mode1"); + cdrom_raw.TrackMode = YellowMode2; + } else { + cdio_debug("Retrying mode1 request as mode2"); + cdrom_raw.TrackMode = XAForm2; + } + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_RAW_READ, &cdrom_raw, + sizeof(RAW_READ_INFO), buf, + sizeof(buf), &dwBytesReturned, NULL ) + == 0 ) { + cdio_debug("Last-ditch effort reading as CDDA"); + cdrom_raw.TrackMode = CDDA; + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_RAW_READ, &cdrom_raw, + sizeof(RAW_READ_INFO), buf, + sizeof(buf), &dwBytesReturned, NULL ) + == 0 ) { + cdio_info("Error reading %lu (%ld)\n", lsn, GetLastError()); + return 1; + } + } + } + + if (mode2_form2) + memcpy (data, buf, M2RAW_SECTOR_SIZE); + else + memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); + + return 0; +} + +/*! + Initialize internal structures for CD device. + */ +bool +win32ioctl_init_win32 (_img_private_t *env) +{ + char psz_win32_drive[7]; + unsigned int len=strlen(env->gen.source_name); + + cdio_debug("using winNT/2K/XP ioctl layer"); + + if (cdio_is_device_win32(env->gen.source_name)) { + sprintf( psz_win32_drive, "\\\\.\\%c:", env->gen.source_name[len-2] ); + + env->h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | + FILE_FLAG_RANDOM_ACCESS, NULL ); + return (env->h_device_handle == NULL) ? false : true; + } + return false; +} + +#endif /*HAVE_WIN32_CDROM*/