📄 win32_ioctl.c
字号:
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 ) { char *psz_msg = NULL; long int i_err = GetLastError(); FORMAT_ERROR(i_err, psz_msg); cdio_info("Error reading audio-mode %lu\n%s)", (long unsigned int) lsn, psz_msg); LocalFree(psz_msg); return 1; } return 0;}/*! Reads a single raw sector using the DeviceIoControl method into data starting from lsn. Returns 0 if no error. */static intread_raw_sector (const _img_private_t *p_env, void *p_buf, lsn_t lsn) { scsi_mmc_cdb_t cdb = {{0, }}; /* ReadCD CDB12 command. The values were taken from MMC1 draft paper. */ CDIO_MMC_SET_COMMAND (cdb.field, CDIO_MMC_GPCMD_READ_CD); CDIO_MMC_SET_READ_LBA (cdb.field, lsn); CDIO_MMC_SET_READ_LENGTH24(cdb.field, 1); cdb.field[9]=0xF8; /* Raw read, 2352 bytes per sector */ return run_scsi_cmd_win32ioctl(p_env, OP_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, CDIO_CD_FRAMESIZE_RAW, p_buf);}/*! Reads a single mode2 sector using the DeviceIoControl method into data starting from lsn. Returns 0 if no error. */intread_mode2_sector_win32ioctl (const _img_private_t *p_env, void *p_data, lsn_t lsn, bool b_form2){ char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; int ret = read_raw_sector (p_env, buf, lsn); if ( 0 != ret) return ret; memcpy (p_data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_XA_HEADER, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); return 0;}/*! Reads a single mode2 sector using the DeviceIoControl method into data starting from lsn. Returns 0 if no error. */intread_mode1_sector_win32ioctl (const _img_private_t *env, void *data, lsn_t lsn, bool b_form2){ char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; int ret = read_raw_sector (env, buf, lsn); if ( 0 != ret) return ret; memcpy (data, buf + CDIO_CD_SYNC_SIZE+CDIO_CD_HEADER_SIZE, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); return 0;}/*! Initialize internal structures for CD device. */boolinit_win32ioctl (_img_private_t *env){#ifdef WIN32 OSVERSIONINFO ov;#endif#ifdef _XBOX ANSI_STRING filename; OBJECT_ATTRIBUTES attributes; IO_STATUS_BLOCK status; HANDLE hDevice; NTSTATUS error;#else unsigned int len=strlen(env->gen.source_name); char psz_win32_drive[7]; DWORD dw_access_flags;#endif cdio_debug("using winNT/2K/XP ioctl layer");#ifdef WIN32 memset(&ov,0,sizeof(OSVERSIONINFO)); ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); GetVersionEx(&ov); if((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4)) dw_access_flags = GENERIC_READ|GENERIC_WRITE; /* add gen write on W2k/XP */ else dw_access_flags = GENERIC_READ;#endif if (cdio_is_device_win32(env->gen.source_name)) {#ifdef _XBOX // Use XBOX cdrom, no matter what drive letter is given. RtlInitAnsiString(&filename,"\\Device\\Cdrom0"); InitializeObjectAttributes(&attributes, &filename, OBJ_CASE_INSENSITIVE, NULL); error = NtCreateFile( &hDevice, GENERIC_READ |SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attributes, &status, NULL, 0, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(error)) { return false; } env->h_device_handle = hDevice;#else sprintf( psz_win32_drive, "\\\\.\\%c:", env->gen.source_name[len-2] ); env->h_device_handle = CreateFile( psz_win32_drive, dw_access_flags, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( env->h_device_handle == INVALID_HANDLE_VALUE ) { /* No good. try toggle write. */ dw_access_flags ^= GENERIC_WRITE; env->h_device_handle = CreateFile( psz_win32_drive, dw_access_flags, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (env->h_device_handle == NULL) return false; }#endif env->b_ioctl_init = true; return true; } return false;}/*! Read and cache the CD's Track Table of Contents and track info. via a SCSI MMC READ_TOC (FULTOC). Return true if successful or false if an error.*/static boolread_fulltoc_win32mmc (_img_private_t *p_env) { scsi_mmc_cdb_t cdb = {{0, }}; CDROM_TOC_FULL cdrom_toc_full; int i_status, i, i_track_format, i_seen_flag; /* Operation code */ CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); cdb.field[1] = 0x00; /* Format */ cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; memset(&cdrom_toc_full, 0, sizeof(cdrom_toc_full)); /* Setup to read header, to get length of data */ CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(cdrom_toc_full)); i_status = run_scsi_cmd_win32ioctl (p_env, 1000*60*3, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, sizeof(cdrom_toc_full), &cdrom_toc_full); if ( 0 != i_status ) { cdio_debug ("SCSI MMC READ_TOC failed\n"); return false; } i_seen_flag=0; for( i = 0 ; i <= CDIO_CD_MAX_TRACKS+3; i++ ) { if ( 0xA0 == cdrom_toc_full.TrackData[i].POINT ) { /* First track number */ p_env->gen.i_first_track = cdrom_toc_full.TrackData[i].PMIN; i_track_format = cdrom_toc_full.TrackData[i].PSEC; i_seen_flag|=0x01; } if ( 0xA1 == cdrom_toc_full.TrackData[i].POINT ) { /* Last track number */ p_env->gen.i_tracks = cdrom_toc_full.TrackData[i].PMIN - p_env->gen.i_first_track + 1; i_seen_flag|=0x02; } if ( 0xA2 == cdrom_toc_full.TrackData[i].POINT ) { /* Start position of the lead out */ p_env->tocent[ p_env->gen.i_tracks ].start_lsn = cdio_msf3_to_lba( cdrom_toc_full.TrackData[i].PMIN, cdrom_toc_full.TrackData[i].PSEC, cdrom_toc_full.TrackData[i].PFRAME ); p_env->tocent[ p_env->gen.i_tracks ].Control = cdrom_toc_full.TrackData[i].Control; p_env->tocent[ p_env->gen.i_tracks ].Format = i_track_format; i_seen_flag|=0x04; } if (cdrom_toc_full.TrackData[i].POINT > 0 && cdrom_toc_full.TrackData[i].POINT <= p_env->gen.i_tracks) { p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].start_lsn = cdio_msf3_to_lba( cdrom_toc_full.TrackData[i].PMIN, cdrom_toc_full.TrackData[i].PSEC, cdrom_toc_full.TrackData[i].PFRAME ); p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].Control = cdrom_toc_full.TrackData[i].Control; p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].Format = i_track_format; cdio_debug("p_sectors: %i, %lu", i, (unsigned long int) (p_env->tocent[i].start_lsn)); if (cdrom_toc_full.TrackData[i].POINT == p_env->gen.i_tracks) i_seen_flag|=0x08; } if ( 0x0F == i_seen_flag ) break; } if ( 0x0F == i_seen_flag ) { p_env->gen.toc_init = true; return true; } return false;}/*! Read and cache the CD's Track Table of Contents and track info. Return true if successful or false if an error.*/boolread_toc_win32ioctl (_img_private_t *p_env) { CDROM_TOC cdrom_toc; DWORD dwBytesReturned; unsigned int i; if ( ! p_env ) return false; if ( read_fulltoc_win32mmc(p_env) ) return true; /* SCSI-MMC READ_TOC (FULTOC) read failed. Try reading TOC via DeviceIoControl instead */ if( DeviceIoControl( p_env->h_device_handle, IOCTL_CDROM_READ_TOC, NULL, 0, &cdrom_toc, sizeof(CDROM_TOC), &dwBytesReturned, NULL ) == 0 ) { char *psz_msg = NULL; long int i_err = GetLastError(); FORMAT_ERROR(i_err, psz_msg); if (psz_msg) { cdio_warn("could not read TOC (%ld): %s", i_err, psz_msg); LocalFree(psz_msg); } else cdio_warn("could not read TOC (%ld)", i_err); return false; } p_env->gen.i_first_track = cdrom_toc.FirstTrack; p_env->gen.i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1; for( i = 0 ; i <= p_env->gen.i_tracks ; i++ ) { p_env->tocent[ i ].start_lsn = cdio_msf3_to_lba( cdrom_toc.TrackData[i].Address[1], cdrom_toc.TrackData[i].Address[2], cdrom_toc.TrackData[i].Address[3] ); p_env->tocent[ i ].Control = cdrom_toc.TrackData[i].Control; p_env->tocent[ i ].Format = cdrom_toc.TrackData[i].Format; cdio_debug("p_sectors: %i, %lu", i, (unsigned long int) (p_env->tocent[i].start_lsn)); } p_env->gen.toc_init = true; return true;}/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */char *get_mcn_win32ioctl (const _img_private_t *env) { DWORD dwBytesReturned; SUB_Q_MEDIA_CATALOG_NUMBER mcn; CDROM_SUB_Q_DATA_FORMAT q_data_format; memset( &mcn, 0, sizeof(mcn) ); q_data_format.Format = CDIO_SUBCHANNEL_MEDIA_CATALOG; q_data_format.Track=1; if( DeviceIoControl( env->h_device_handle, IOCTL_CDROM_READ_Q_CHANNEL, &q_data_format, sizeof(q_data_format), &mcn, sizeof(mcn), &dwBytesReturned, NULL ) == 0 ) { cdio_warn( "could not read Q Channel at track %d", 1); } else if (mcn.Mcval) return strdup(mcn.MediaCatalog); return NULL;}/*! Get the format (XA, DATA, AUDIO) of a track. */track_format_tget_track_format_win32ioctl(const _img_private_t *env, track_t i_track) { /* This is pretty much copied from the "badly broken" cdrom_count_tracks in linux/cdrom.c. */ if (env->tocent[i_track - env->gen.i_first_track].Control & 0x04) { if (env->tocent[i_track - env->gen.i_first_track].Format == 0x10) return TRACK_FORMAT_CDI; else if (env->tocent[i_track - env->gen.i_first_track].Format == 0x20) return TRACK_FORMAT_XA; else return TRACK_FORMAT_DATA; } else return TRACK_FORMAT_AUDIO;}#endif /*HAVE_WIN32_CDROM*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -