From 5cc6105b392b202bbded1d39915742192c88fc95 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 13 Jan 2002 01:44:00 +0000 Subject: [PATCH] Changed the Wine internal cdrom interface to the NT model. --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/cdrom.c | 996 +++++++++++++++++++++++++++++++++++++++++ files/drive.c | 263 ++++++++++- files/file.c | 5 + include/cdrom.h | 109 ----- include/file.h | 6 + include/ntddcdrm.h | 167 +++++++ include/ntddstor.h | 229 ++++++++++ include/winioctl.h | 79 +++- misc/Makefile.in | 1 - misc/cdrom.c | 908 ------------------------------------- win32/device.c | 53 ++- 12 files changed, 1778 insertions(+), 1039 deletions(-) create mode 100644 dlls/ntdll/cdrom.c delete mode 100644 include/cdrom.h create mode 100644 include/ntddcdrm.h create mode 100644 include/ntddstor.h delete mode 100644 misc/cdrom.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index a4bc895f59d..c48977f682c 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -6,6 +6,7 @@ MODULE = ntdll EXTRALIBS = $(LIBUNICODE) C_SRCS = \ + cdrom.c \ critsection.c \ debugtools.c \ exception.c \ diff --git a/dlls/ntdll/cdrom.c b/dlls/ntdll/cdrom.c new file mode 100644 index 00000000000..1d56296ee87 --- /dev/null +++ b/dlls/ntdll/cdrom.c @@ -0,0 +1,996 @@ +/* -*- tab-width: 8; c-basic-offset: 4 -*- */ +/* Main file for CD-ROM support + * + * Copyright 1994 Martin Ayotte + * Copyright 1999, 2001 Eric Pouech + * Copyright 2000 Andreas Mohr + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include "ntddk.h" +#include "winioctl.h" +#include "ntddstor.h" +#include "ntddcdrm.h" +#include "drive.h" +#include "file.h" +#include "debugtools.h" + +#ifdef HAVE_LINUX_CDROM_H +# include +#endif +#ifdef HAVE_LINUX_UCDROM_H +# include +#endif +#ifdef HAVE_SYS_CDIO_H +# include +#endif + +DEFAULT_DEBUG_CHANNEL(cdrom); + +/* FIXME: this is needed because we can't open simultaneously several times /dev/cdrom + * this should be removed when a proper device interface is implemented + */ +struct cdrom_cache { + int fd; + int count; +}; +static struct cdrom_cache cdrom_cache[26]; + +/****************************************************************** + * CDROM_Open + * + * + */ +static int CDROM_Open(HANDLE hDevice, DWORD clientID) +{ + int dev = LOWORD(clientID); + + if (dev >= 26) return -1; + + if (!cdrom_cache[dev].count) + { + char root[4]; + + strcpy(root, "A:\\"); + root[0] += dev; + if (GetDriveTypeA(root) != DRIVE_CDROM) return -1; + cdrom_cache[dev].fd = open(DRIVE_GetDevice(dev), O_RDONLY|O_NONBLOCK); + if (cdrom_cache[dev].fd == -1) + { + FIXME("Can't open %s: %s\n", root, strerror(errno)); + return -1; + } + } + cdrom_cache[dev].count++; + return cdrom_cache[dev].fd; +} + +/****************************************************************** + * CDROM_Close + * + * + */ +static void CDROM_Close(DWORD clientID, int fd) +{ + int dev = LOWORD(clientID); + + if (dev >= 26 || fd != cdrom_cache[dev].fd) FIXME("how come\n"); + if (--cdrom_cache[dev].count == 0) + close(cdrom_cache[dev].fd); +} + +/****************************************************************** + * CDROM_GetStatusCode + * + * + */ +static DWORD CDROM_GetStatusCode(int io) +{ + if (io == 0) return 0; + switch (errno) + { + case EIO: return STATUS_NO_MEDIA_IN_DEVICE; + } + FIXME("Unmapped error code %d: %s\n", errno, strerror(errno)); + return STATUS_IO_DEVICE_ERROR; +} + +static DWORD CDROM_GetControl(int dev, CDROM_AUDIO_CONTROL* cac) +{ + cac->LbaFormat = 0; /* FIXME */ + cac->LogicalBlocksPerSecond = 1; /* FIXME */ + return STATUS_NOT_SUPPORTED; +} + +static DWORD CDROM_GetDeviceNumber(int dev, STORAGE_DEVICE_NUMBER* devnum) +{ + return STATUS_NOT_SUPPORTED; +} + +static DWORD CDROM_GetDriveGeometry(int dev, DISK_GEOMETRY* dg) +{ +#if 0 + dg->Cylinders.s.LowPart = 1; /* FIXME */ + dg->Cylinders.s.HighPart = 0; /* FIXME */ + dg->MediaType = 1; /* FIXME */ + dg->TracksPerCylinder = 1; /* FIXME */ + dg->SectorsPerTrack = 1; /* FIXME */ + dg->BytesPerSector= 1; /* FIXME */ +#endif + return STATUS_NOT_SUPPORTED; +} + +/************************************************************************** + * CDROM_Reset [internal] + */ +static DWORD CDROM_ResetAudio(int dev) +{ +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, CDROMRESET)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode(ioctl(dev, CDIOCRESET, NULL)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_SetTray + * + * + */ +static DWORD CDROM_SetTray(int dev, BOOL doEject) +{ +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, doEject ? CDROMEJECT : CDROMCLOSETRAY)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode((ioctl(dev, CDIOCALLOW, NULL)) || + (ioctl(dev, doEject ? CDIOCEJECT : CDIOCCLOSE, NULL)) || + (ioctl(dev, CDIOCPREVENT, NULL))); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_ControlEjection + * + * + */ +static DWORD CDROM_ControlEjection(int dev, const PREVENT_MEDIA_REMOVAL* rmv) +{ + int val = rmv->PreventMediaRemoval; +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, CDROM_LOCKDOOR, val)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode(ioctl(dev, (val) ? CDIOPREVENT : CDIOCALLOW, NULL)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_ReadTOC + * + * + */ +static DWORD CDROM_ReadTOC(int dev, CDROM_TOC* toc) +{ + DWORD ret = STATUS_NOT_SUPPORTED; + +#if defined(linux) + int i, io = -1; + struct cdrom_tochdr hdr; + struct cdrom_tocentry entry; + + io = ioctl(dev, CDROMREADTOCHDR, &hdr); + if (io == -1) + { + WARN("(%d) -- Error occurred (%s)!\n", dev, strerror(errno)); + goto end; + } + toc->FirstTrack = hdr.cdth_trk0; + toc->LastTrack = hdr.cdth_trk1; + + TRACE("from=%d to=%d\n", toc->FirstTrack, toc->LastTrack); + + for (i = toc->FirstTrack; i <= toc->LastTrack + 1; i++) + { + if (i == toc->LastTrack + 1) + { + entry.cdte_track = CDROM_LEADOUT; + } else { + entry.cdte_track = i; + } + entry.cdte_format = CDROM_MSF; + io = ioctl(dev, CDROMREADTOCENTRY, &entry); + if (io == -1) { + WARN("error read entry (%s)\n", strerror(errno)); + goto end; + } + toc->TrackData[i - toc->FirstTrack].Control = entry.cdte_ctrl; + toc->TrackData[i - toc->FirstTrack].Adr = entry.cdte_adr; + /* marking last track with leadout value as index */ + toc->TrackData[i - toc->FirstTrack].TrackNumber = entry.cdte_track; + toc->TrackData[i - toc->FirstTrack].Address[0] = 0; + toc->TrackData[i - toc->FirstTrack].Address[1] = entry.cdte_addr.msf.minute; + toc->TrackData[i - toc->FirstTrack].Address[2] = entry.cdte_addr.msf.second; + toc->TrackData[i - toc->FirstTrack].Address[3] = entry.cdte_addr.msf.frame; + } +end: + ret = CDROM_GetStatusCode(io); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + int i, io = -1; + struct ioc_toc_header hdr; + struct ioc_read_toc_entry entry; + struct cd_toc_entry toc_buffer; + + io = ioctl(dev, CDIOREADTOCHEADER, &hdr); + if (io == -1) + { + WARN("(%d) -- Error occurred (%s)!\n", dev, strerror(errno)); + goto end; + } + toc->FirstTrack = hdr.starting_track; + toc->LastTrack = hdr.ending_track; + + TRACE("from=%d to=%d\n", toc->FirstTrack, toc->LastTrack); + + for (i = toc->FirstTrack; i <= toc->LastTrack + 1; i++) + { + if (i == toc->LastTrack + 1) + { +#define LEADOUT 0xaa + entry.starting_track = LEADOUT; + } else { + entry.starting_track = i; + } + memset((char *)&toc_buffer, 0, sizeof(toc_buffer)); + entry.address_format = CD_MSF_FORMAT; + entry.data_len = sizeof(toc_buffer); + entry.data = &toc_buffer; + io = ioctl(dev, CDIOREADTOCENTRYS, &entry); + if (io == -1) { + WARN("error read entry (%s)\n", strerror(errno)); + goto end; + } + toc->TrackData[i - toc->FirstTrack].Control = toc_buffer.control; + toc->TrackData[i - toc->FirstTrack].Adr = toc_buffer.addr_type; + /* marking last track with leadout value as index */ + toc->TrackData[i - toc->FirstTrack].TrackNumber = entry.starting_track; + toc->TrackData[i - toc->FirstTrack].Address[0] = 0; + toc->TrackData[i - toc->FirstTrack].Address[1] = toc_buffer.addr.msf.minute; + toc->TrackData[i - toc->FirstTrack].Address[2] = toc_buffer.addr.msf.second; + toc->TrackData[i - toc->FirstTrack].Address[3] = toc_buffer.addr.msf.frame; + } +end: + ret = CDROM_GetStatusCode(io); +#else + ret = STATUS_NOT_SUPPORTED; +#endif + return ret; +} + +/****************************************************************** + * CDROM_GetDiskData + * + * + */ +static DWORD CDROM_GetDiskData(int dev, CDROM_DISK_DATA* data) +{ + CDROM_TOC toc; + DWORD ret; + int i; + + if ((ret = CDROM_ReadTOC(dev, &toc)) != 0) return ret; + data->DiskData = 0; + for (i = toc.FirstTrack; i <= toc.LastTrack; i++) { + if (toc.TrackData[i].Control & 0x04) + data->DiskData |= CDROM_DISK_DATA_TRACK; + else + data->DiskData |= CDROM_DISK_AUDIO_TRACK; + } + return 0; +} + +/****************************************************************** + * CDROM_ReadQChannel + * + * + */ +static DWORD CDROM_ReadQChannel(int dev, const CDROM_SUB_Q_DATA_FORMAT* fmt, + SUB_Q_CHANNEL_DATA* data) +{ + DWORD ret = STATUS_NOT_SUPPORTED; + unsigned size; + SUB_Q_HEADER* hdr = (SUB_Q_HEADER*)data; + int io; + +#ifdef linux + struct cdrom_subchnl sc; + sc.cdsc_format = CDROM_MSF; + + io = ioctl(dev, CDROMSUBCHNL, &sc); + if (io == -1) + { + TRACE("opened or no_media (%s)!\n", strerror(errno)); + hdr->AudioStatus = AUDIO_STATUS_NO_STATUS; + goto end; + } + + hdr->AudioStatus = AUDIO_STATUS_NOT_SUPPORTED; + + switch (sc.cdsc_audiostatus) { + case CDROM_AUDIO_INVALID: + hdr->AudioStatus = AUDIO_STATUS_NOT_SUPPORTED; + break; + case CDROM_AUDIO_NO_STATUS: + hdr->AudioStatus = AUDIO_STATUS_NO_STATUS; + break; + case CDROM_AUDIO_PLAY: + hdr->AudioStatus = AUDIO_STATUS_IN_PROGRESS; + break; + case CDROM_AUDIO_PAUSED: + hdr->AudioStatus = AUDIO_STATUS_PAUSED; + break; + case CDROM_AUDIO_COMPLETED: + hdr->AudioStatus = AUDIO_STATUS_PLAY_COMPLETE; + break; + case CDROM_AUDIO_ERROR: + hdr->AudioStatus = AUDIO_STATUS_PLAY_ERROR; + break; + default: + TRACE("status=%02X !\n", sc.cdsc_audiostatus); + break; + } + switch (fmt->Format) + { + case IOCTL_CDROM_CURRENT_POSITION: + size = sizeof(SUB_Q_CURRENT_POSITION); + data->CurrentPosition.FormatCode = sc.cdsc_format; + data->CurrentPosition.Control = sc.cdsc_ctrl; + data->CurrentPosition.ADR = sc.cdsc_adr; + data->CurrentPosition.TrackNumber = sc.cdsc_trk; + data->CurrentPosition.IndexNumber = sc.cdsc_ind; + + data->CurrentPosition.AbsoluteAddress[0] = 0; + data->CurrentPosition.AbsoluteAddress[1] = sc.cdsc_absaddr.msf.minute; + data->CurrentPosition.AbsoluteAddress[2] = sc.cdsc_absaddr.msf.second; + data->CurrentPosition.AbsoluteAddress[3] = sc.cdsc_absaddr.msf.frame; + + data->CurrentPosition.TrackRelativeAddress[0] = 0; + data->CurrentPosition.TrackRelativeAddress[1] = sc.cdsc_reladdr.msf.minute; + data->CurrentPosition.TrackRelativeAddress[2] = sc.cdsc_reladdr.msf.second; + data->CurrentPosition.TrackRelativeAddress[3] = sc.cdsc_reladdr.msf.frame; + break; + case IOCTL_CDROM_MEDIA_CATALOG: + size = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); + data->MediaCatalog.FormatCode = IOCTL_CDROM_MEDIA_CATALOG; + { + struct cdrom_mcn mcn; + if ((io = ioctl(dev, CDROM_GET_MCN, &mcn)) == -1) goto end; + + data->MediaCatalog.FormatCode = IOCTL_CDROM_MEDIA_CATALOG; + data->MediaCatalog.Mcval = 0; /* FIXME */ + memcpy(data->MediaCatalog.MediaCatalog, mcn.medium_catalog_number, 14); + data->MediaCatalog.MediaCatalog[14] = 0; + } + break; + case IOCTL_CDROM_TRACK_ISRC: + size = sizeof(SUB_Q_CURRENT_POSITION); + FIXME("TrackIsrc: NIY on linux"); + data->TrackIsrc.FormatCode = IOCTL_CDROM_TRACK_ISRC; + data->TrackIsrc.Tcval = 0; + io = 0; + break; + } + + end: + ret = CDROM_GetStatusCode(io); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + struct ioc_read_subchannel read_sc; + struct cd_sub_channel_info sc; + + read_sc.address_format = CD_MSF_FORMAT; + read_sc.track = 0; + read_sc.data_len = sizeof(sc); + read_sc.data = ≻ + switch (fmt->Format) + { + case IOCTL_CDROM_CURRENT_POSITION: + read_sc.data_format = CD_CURRENT_POSITION; + break; + case IOCTL_CDROM_MEDIA_CATALOG: + read_sc.data_format = CD_MEDIA_CATALOG; + break; + case IOCTL_CDROM_TRACK_ISRC: + read_sc.data_format = CD_TRACK_INFO; + sc.track_info.track_number = data->TrackIsrc.Track; + break; + } + io = ioctl(dev, CDIOCREADSUBCHANNEL, &read_sc); + if (io == -1) + { + TRACE("opened or no_media (%s)!\n", strerror(errno)); + hdr->AudioStatus = AUDIO_STATUS_NO_STATUS; + goto end; + } + + hdr->AudioStatus = AUDIO_STATUS_NOT_SUPPORTED; + + switch (sc.header.audio_status) { + case CD_AS_AUDIO_INVALID: + hdr->AudioStatus = AUDIO_STATUS_NOT_SUPPORTED; + break; + case CD_AS_NO_STATUS: + hdr->AudioStatus = AUDIO_STATUS_NO_STATUS; + break; + case CD_AS_PLAY_IN_PROGRESS: + hdr->AudioStatus = AUDIO_STATUS_IN_PROGRESS; + break; + case CD_AS_PLAY_PAUSED: + hdr->AudioStatus = AUDIO_STATUS_IN_PAUSED; + break; + case CD_AS_PLAY_AUDIO_COMPLETED: + hdr->AudioStatus = AUDIO_STATUS_PLAY_COMPLETE; + break; + case CD_AS_PLAY_ERROR: + hdr->AudioStatus = AUDIO_STATUS_PLAY_ERROR; + break; + default: + TRACE("status=%02X !\n", sc.header.audio_status); + } + switch (fmt->Format) + { + case IOCTL_CDROM_CURRENT_POSITION: + size = sizeof(SUB_Q_CURRENT_POSITION); + data->CurrentPosition.FormatCode = sc.position.data_format; + data->CurrentPosition.Control = sc.position.control; + data->CurrentPosition.ADR = sc.position.addr_type; + data->CurrentPosition.TrackNumber = sc.position.track_number; + data->CurrentPosition.IndexNumber = sc.position.index_number; + + data->CurrentPosition.AbsoluteAddress[0] = 0; + data->CurrentPosition.AbsoluteAddress[1] = sc.position.absaddr.msf.minute; + data->CurrentPosition.AbsoluteAddress[2] = sc.position.absaddr.msf.second; + data->CurrentPosition.AbsoluteAddress[3] = sc.position.absaddr.msf.frame; + data->CurrentPosition.TrackRelativeAddress[0] = 0; + data->CurrentPosition.TrackRelativeAddress[1] = sc.position.reladdr.msf.minute; + data->CurrentPosition.TrackRelativeAddress[2] = sc.position.reladdr.msf.second; + data->CurrentPosition.TrackRelativeAddress[3] = sc.position.reladdr.msf.frame; + break; + case IOCTL_CDROM_MEDIA_CATALOG: + size = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); + data->MediaCatalog.FormatCode = IOCTL_CDROM_MEDIA_CATALOG; + data->MediaCatalog.FormatCode = sc.media_catalog.data_format; + data->MediaCatalog.Mcval = sc.media_catalog.mc_valid; + memcpy(data->MediaCatalog.MediaCatalog, sc.media_catalog.mc_number, 15); + break; + case IOCTL_CDROM_TRACK_ISRC: + size = sizeof(SUB_Q_CURRENT_POSITION); + data->TrackIsrc.Tcval = sc.track_info.ti_valid; + memcpy(data->TrackIsrc.TrackIsrc, sc.track_info.ti_number, 15); + break; + } + + end: + ret = CDROM_GetStatusCode(io); +#endif + return ret; +} + +/****************************************************************** + * CDROM_Verify + * + * + */ +static DWORD CDROM_Verify(int dev) +{ + /* quick implementation */ + CDROM_SUB_Q_DATA_FORMAT fmt; + SUB_Q_CHANNEL_DATA data; + + fmt.Format = IOCTL_CDROM_CURRENT_POSITION; + return CDROM_ReadQChannel(dev, &fmt, &data) ? 0 : 1; +} + +/****************************************************************** + * CDROM_PlayAudioMSF + * + * + */ +static DWORD CDROM_PlayAudioMSF(int dev, const CDROM_PLAY_AUDIO_MSF* audio_msf) +{ + DWORD ret = STATUS_NOT_SUPPORTED; +#ifdef linux + struct cdrom_msf msf; + int io; + + msf.cdmsf_min0 = audio_msf->StartingM; + msf.cdmsf_sec0 = audio_msf->StartingS; + msf.cdmsf_frame0 = audio_msf->StartingF; + msf.cdmsf_min1 = audio_msf->EndingM; + msf.cdmsf_sec1 = audio_msf->EndingS; + msf.cdmsf_frame1 = audio_msf->EndingF; + + io = ioctl(dev, CDROMSTART); + if (io == -1) + { + WARN("motor doesn't start !\n"); + goto end; + } + io = ioctl(dev, CDROMPLAYMSF, &msf); + if (io == -1) + { + WARN("device doesn't play !\n"); + goto end; + } + TRACE("msf = %d:%d:%d %d:%d:%d\n", + msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0, + msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1); + end: + ret = CDROM_GetStatusCode(io); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + struct ioc_play_msf msf; + int io; + + msf.start_m = audio_msf->StartingM; + msf.start_s = audio_msf->StartingS; + msf.start_f = audio_msf->StartingF; + msf.end_m = audio_msf->EndingM; + msf.end_s = audio_msf->EndingS; + msf.end_f = audio_msf->EndingF; + + io = ioctl(dev, CDIOCSTART, NULL); + if (io == -1) + { + WARN("motor doesn't start !\n"); + goto end; + } + io = ioctl(dev, CDIOCPLAYMSF, &msf); + if (io == -1) + { + WARN("device doesn't play !\n"); + goto end; + } + TRACE("msf = %d:%d:%d %d:%d:%d\n", + msf.start_m, msf.start_s, msf.start_f, + msf.end_m, msf.end_s, msf.end_f); +end: + ret = CDROM_GetStatusCode(io); +#endif + return ret; +} + +/****************************************************************** + * CDROM_SeekAudioMSF + * + * + */ +static DWORD CDROM_SeekAudioMSF(int dev, const CDROM_SEEK_AUDIO_MSF* audio_msf) +{ +#if defined(linux) + struct cdrom_msf0 msf; + msf.minute = audio_msf->M; + msf.second = audio_msf->S; + msf.frame = audio_msf->F; + + return CDROM_GetStatusCode(ioctl(dev, CDROMSEEK, &msf)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + FIXME("Could a BSD expert implement the seek function ?\n"); + return STATUS_NOT_SUPPORTED; +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_PauseAudio + * + * + */ +static DWORD CDROM_PauseAudio(int dev) +{ +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, CDROMPAUSE)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode(ioctl(dev, CDIOCPAUSE, NULL)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_ResumeAudio + * + * + */ +static DWORD CDROM_ResumeAudio(int dev) +{ +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, CDROMRESUME)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode(ioctl(dev, CDIOCRESUME, NULL)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_StopAudio + * + * + */ +static DWORD CDROM_StopAudio(int dev) +{ +#if defined(linux) + return CDROM_GetStatusCode(ioctl(dev, CDROMSTOP)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + return CDROM_GetStatusCode(ioctl(dev, CDIOCSTOP, NULL)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_GetVolume + * + * + */ +static DWORD CDROM_GetVolume(int dev, VOLUME_CONTROL* vc) +{ +#if defined(linux) + struct cdrom_volctrl volc; + int io; + + io = ioctl(dev, CDROMVOLREAD, &volc); + if (io != -1) + { + vc->PortVolume[0] = volc.channel0; + vc->PortVolume[1] = volc.channel1; + vc->PortVolume[2] = volc.channel2; + vc->PortVolume[3] = volc.channel3; + } + return CDROM_GetStatusCode(io); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + struct ioc_vol volc; + int io; + + io = ioctl(dev, CDIOCGETVOL, &volc); + if (io != -1) + { + vc->PortVolume[0] = volc.vol[0]; + vc->PortVolume[1] = volc.vol[1]; + vc->PortVolume[2] = volc.vol[2]; + vc->PortVolume[3] = volc.vol[3]; + } + return CDROM_GetStatusCode(io); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_SetVolume + * + * + */ +static DWORD CDROM_SetVolume(int dev, const VOLUME_CONTROL* vc) +{ +#if defined(linux) + struct cdrom_volctrl volc; + + volc.channel0 = vc->PortVolume[0]; + volc.channel1 = vc->PortVolume[1]; + volc.channel2 = vc->PortVolume[2]; + volc.channel3 = vc->PortVolume[3]; + + return CDROM_GetStatusCode(ioctl(dev, CDROMVOLCTRL, &volc)); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + struct ioc_vol volc; + + volc.vol[0] = vc->PortVolume[0]; + volc.vol[1] = vc->PortVolume[1]; + volc.vol[2] = vc->PortVolume[2]; + volc.vol[3] = vc->PortVolume[3]; + + return CDROM_GetStatusCode(ioctl(dev, CDIOCSETVOL, &volc)); +#else + return STATUS_NOT_SUPPORTED; +#endif +} + +/****************************************************************** + * CDROM_RawRead + * + * + */ +static DWORD CDROM_RawRead(int dev, const RAW_READ_INFO* raw, void* buffer, DWORD len, DWORD* sz) +{ + int ret = STATUS_NOT_SUPPORTED; + int io = -1; + DWORD sectSize; + + switch (raw->TrackMode) + { + case YellowMode2: sectSize = 2336; break; + case XAForm2: sectSize = 2328; break; + case CDDA: sectSize = 2352; break; + default: return STATUS_INVALID_PARAMETER; + } + if (len < raw->SectorCount * sectSize) return STATUS_BUFFER_TOO_SMALL; + /* strangely enough, it seems that sector offsets are always indicated with a size of 2048, + * even if a larger size if read... + */ +#if defined(linux) + { + struct cdrom_read cdr; + struct cdrom_read_audio cdra; + + switch (raw->TrackMode) + { + case YellowMode2: + if (raw->DiskOffset.s.HighPart) FIXME("Unsupported value\n"); + cdr.cdread_lba = raw->DiskOffset.s.LowPart; /* FIXME ? */ + cdr.cdread_bufaddr = buffer; + cdr.cdread_buflen = raw->SectorCount * sectSize; + io = ioctl(dev, CDROMREADMODE2, &cdr); + break; + case XAForm2: + FIXME("XAForm2: NIY\n"); + return ret; + case CDDA: + /* FIXME: the output doesn't seem 100% correct... in fact output is shifted + * between by NT2K box and this... should check on the same drive... + * otherwise, I fear a 2352/2368 mismatch somewhere in one of the drivers + * (linux/NT). + * Anyway, that's not critical at all. We're talking of 16/32 bytes, we're + * talking of 0.2 ms of sound + */ + /* 2048 = 2 ** 11 */ + if (raw->DiskOffset.s.HighPart & ~2047) FIXME("Unsupported value\n"); + cdra.addr.lba = ((raw->DiskOffset.s.LowPart >> 11) | + (raw->DiskOffset.s.HighPart << (32 - 11))) - 1; + FIXME("reading at %u\n", cdra.addr.lba); + cdra.addr_format = CDROM_LBA; + cdra.nframes = raw->SectorCount; + cdra.buf = buffer; + io = ioctl(dev, CDROMREADAUDIO, &cdra); + break; + } + } + *sz = sectSize * raw->SectorCount; + ret = CDROM_GetStatusCode(io); +#elif defined(__FreeBSD__) || defined(__NetBSD__) + { + struct ioc_read_audio ira; + + switch (raw->TrackMode) + { + case YellowMode2: + FIXME("YellowMode2: NIY\n"); + return ret; + case XAForm2: + FIXME("XAForm2: NIY\n"); + return ret; + case CDDA: + /* 2048 = 2 ** 11 */ + if (raw->DiskOffset.s.HighPart & ~2047) FIXME("Unsupported value\n"); + ira.address.lba = ((raw->DiskOffset.s.LowPart >> 11) | + raw->DiskOffset.s.HighPart << (32 - 11)) - 1; + ira.address_format = CD_LBA_FORMAT; + ira.nframes = raw->SectorCount; + ira.buffer = buffer; + io = ioctl(dev, CDIOCREADAUDIO, &ira); + break; + } + } + *sz = sectSize * raw->SectorCount; + ret = CDROM_GetStatusCode(io); +#endif + return ret; +} + +/****************************************************************** + * CDROM_DeviceIoControl + * + * + */ +BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode, + LPVOID lpInBuffer, DWORD nInBufferSize, + LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) +{ + DWORD sz; + DWORD error = 0; + int dev; + + TRACE("%lx[%c] %lx %lx %ld %lx %ld %lx %lx\n", + (DWORD)hDevice, 'A' + LOWORD(clientID), dwIoControlCode, (DWORD)lpInBuffer, nInBufferSize, + (DWORD)lpOutBuffer, nOutBufferSize, (DWORD)lpBytesReturned, (DWORD)lpOverlapped); + + if (lpBytesReturned) *lpBytesReturned = 0; + if (lpOverlapped) + { + FIXME("Overlapped isn't implemented yet\n"); + SetLastError(STATUS_NOT_SUPPORTED); + return FALSE; + } + + SetLastError(0); + dev = CDROM_Open(hDevice, clientID); + if (dev == -1) + { + CDROM_GetStatusCode(-1); + return FALSE; + } + + switch (dwIoControlCode) + { + case IOCTL_STORAGE_CHECK_VERIFY: + case IOCTL_CDROM_CHECK_VERIFY: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_Verify(dev); + break; + +/* EPP case IOCTL_STORAGE_CHECK_VERIFY2: */ + +/* EPP case IOCTL_STORAGE_FIND_NEW_DEVICES: */ +/* EPP case IOCTL_CDROM_FIND_NEW_DEVICES: */ + + case IOCTL_STORAGE_LOAD_MEDIA: + case IOCTL_CDROM_LOAD_MEDIA: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_SetTray(dev, FALSE); + break; + case IOCTL_STORAGE_EJECT_MEDIA: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_SetTray(dev, TRUE); + break; + + case IOCTL_DISK_MEDIA_REMOVAL: + case IOCTL_STORAGE_MEDIA_REMOVAL: + case IOCTL_STORAGE_EJECTION_CONTROL: + /* FIXME the last ioctl:s is not the same as the two others... + * lockcount/owner should be handled */ + sz = 0; + if (lpOutBuffer != NULL || nOutBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nInBufferSize < sizeof(PREVENT_MEDIA_REMOVAL)) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_ControlEjection(dev, (const PREVENT_MEDIA_REMOVAL*)lpInBuffer); + break; + +/* EPP case IOCTL_STORAGE_GET_MEDIA_TYPES: */ + + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + sz = sizeof(STORAGE_DEVICE_NUMBER); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetDeviceNumber(dev, (STORAGE_DEVICE_NUMBER*)lpOutBuffer); + break; + + case IOCTL_STORAGE_RESET_DEVICE: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_ResetAudio(dev); + break; + + case IOCTL_CDROM_GET_CONTROL: + sz = sizeof(CDROM_AUDIO_CONTROL); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetControl(dev, (CDROM_AUDIO_CONTROL*)lpOutBuffer); + break; + + case IOCTL_CDROM_GET_DRIVE_GEOMETRY: + sz = sizeof(DISK_GEOMETRY); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetDriveGeometry(dev, (DISK_GEOMETRY*)lpOutBuffer); + break; + + case IOCTL_CDROM_DISK_TYPE: + sz = sizeof(CDROM_DISK_DATA); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetDiskData(dev, (CDROM_DISK_DATA*)lpOutBuffer); + break; + +/* EPP case IOCTL_CDROM_GET_LAST_SESSION: */ + + case IOCTL_CDROM_READ_Q_CHANNEL: + sz = sizeof(SUB_Q_CHANNEL_DATA); + if (lpInBuffer == NULL || nInBufferSize < sizeof(CDROM_SUB_Q_DATA_FORMAT)) + error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_ReadQChannel(dev, (const CDROM_SUB_Q_DATA_FORMAT*)lpInBuffer, + (SUB_Q_CHANNEL_DATA*)lpOutBuffer); + break; + + case IOCTL_CDROM_READ_TOC: + sz = sizeof(CDROM_TOC); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_ReadTOC(dev, (CDROM_TOC*)lpOutBuffer); + break; + +/* EPP case IOCTL_CDROM_READ_TOC_EX: */ + + case IOCTL_CDROM_PAUSE_AUDIO: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_PauseAudio(dev); + break; + case IOCTL_CDROM_PLAY_AUDIO_MSF: + sz = 0; + if (lpOutBuffer != NULL || nOutBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nInBufferSize < sizeof(CDROM_PLAY_AUDIO_MSF)) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_PlayAudioMSF(dev, (const CDROM_PLAY_AUDIO_MSF*)lpInBuffer); + break; + case IOCTL_CDROM_RESUME_AUDIO: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_ResumeAudio(dev); + break; + case IOCTL_CDROM_SEEK_AUDIO_MSF: + sz = 0; + if (lpOutBuffer != NULL || nOutBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nInBufferSize < sizeof(CDROM_SEEK_AUDIO_MSF)) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_SeekAudioMSF(dev, (const CDROM_SEEK_AUDIO_MSF*)lpInBuffer); + break; + case IOCTL_CDROM_STOP_AUDIO: + sz = 0; + if (lpInBuffer != NULL || nInBufferSize != 0 || lpOutBuffer != NULL || nOutBufferSize != 0) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_StopAudio(dev); + break; + case IOCTL_CDROM_GET_VOLUME: + sz = sizeof(VOLUME_CONTROL); + if (lpInBuffer != NULL || nInBufferSize != 0) error = STATUS_INVALID_PARAMETER; + else if (nOutBufferSize < sz) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_GetVolume(dev, (VOLUME_CONTROL*)lpOutBuffer); + break; + case IOCTL_CDROM_SET_VOLUME: + sz = 0; + if (lpInBuffer == NULL || nInBufferSize < sizeof(VOLUME_CONTROL) || lpOutBuffer != NULL) + error = STATUS_INVALID_PARAMETER; + else error = CDROM_SetVolume(dev, (const VOLUME_CONTROL*)lpInBuffer); + break; + case IOCTL_CDROM_RAW_READ: + sz = 0; + if (nInBufferSize < sizeof(RAW_READ_INFO)) error = STATUS_INVALID_PARAMETER; + else if (lpOutBuffer == NULL) error = STATUS_BUFFER_TOO_SMALL; + else error = CDROM_RawRead(dev, (const RAW_READ_INFO*)lpInBuffer, + lpOutBuffer, nOutBufferSize, &sz); + break; + default: + FIXME("Unsupported IOCTL %lx\n", dwIoControlCode); + sz = 0; + error = STATUS_INVALID_PARAMETER; + break; + } + + if (lpBytesReturned) *lpBytesReturned = sz; + if (error) + { + SetLastError(error); + return FALSE; + } + CDROM_Close(clientID, dev); + return TRUE; +} + diff --git a/files/drive.c b/files/drive.c index 809e536f005..91607248cd2 100644 --- a/files/drive.c +++ b/files/drive.c @@ -44,7 +44,6 @@ #include "wine/winbase16.h" /* for GetCurrentTask */ #include "winerror.h" #include "drive.h" -#include "cdrom.h" #include "file.h" #include "heap.h" #include "msdos.h" @@ -52,6 +51,9 @@ #include "task.h" #include "debugtools.h" #include "wine/server.h" +#include "winioctl.h" +#include "ntddstor.h" +#include "ntddcdrm.h" DEFAULT_DEBUG_CHANNEL(dosfs); DECLARE_DEBUG_CHANNEL(file); @@ -459,6 +461,40 @@ const char * DRIVE_GetDevice( int drive ) return (DRIVE_IsValid( drive )) ? DOSDrives[drive].device : NULL; } +/****************************************************************** + * static WORD CDROM_Data_FindBestVoldesc + * + * + */ +static WORD CDROM_Data_FindBestVoldesc(int fd) +{ + BYTE cur_vd_type, max_vd_type = 0; + unsigned int offs, best_offs = 0, extra_offs = 0; + char sig[3]; + + for (offs = 0x8000; offs <= 0x9800; offs += 0x800) + { + /* if 'CDROM' occurs at position 8, this is a pre-iso9660 cd, and + * the volume label is displaced forward by 8 + */ + lseek(fd, offs + 11, SEEK_SET); /* check for non-ISO9660 signature */ + read(fd, &sig, 3); + if ((sig[0] == 'R') && (sig[1] == 'O') && (sig[2]=='M')) + { + extra_offs = 8; + } + lseek(fd, offs + extra_offs, SEEK_SET); + read(fd, &cur_vd_type, 1); + if (cur_vd_type == 0xff) /* voldesc set terminator */ + break; + if (cur_vd_type > max_vd_type) + { + max_vd_type = cur_vd_type; + best_offs = offs + extra_offs; + } + } + return best_offs; +} /*********************************************************************** * DRIVE_ReadSuperblock @@ -567,8 +603,103 @@ int DRIVE_WriteSuperblockEntry (int drive, off_t ofs, size_t len, char * buff) return close (fd); } +/****************************************************************** + * static HANDLE CDROM_Open + * + * + */ +static HANDLE CDROM_Open(int drive) +{ + char root[6]; + strcpy(root, "\\\\.\\A:"); + root[4] += drive; + return CreateFileA(root, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); +} + +/************************************************************************** + * CDROM_Data_GetLabel [internal] + */ +DWORD CDROM_Data_GetLabel(int drive, char *label) +{ +#define LABEL_LEN 32+1 + int dev = open(DOSDrives[drive].device, O_RDONLY|O_NONBLOCK); + WORD offs = CDROM_Data_FindBestVoldesc(dev); + WCHAR label_read[LABEL_LEN]; /* Unicode possible, too */ + DWORD unicode_id = 0; + + if (offs) + { + if ((lseek(dev, offs+0x58, SEEK_SET) == offs+0x58) + && (read(dev, &unicode_id, 3) == 3)) + { + int ver = (unicode_id & 0xff0000) >> 16; + + if ((lseek(dev, offs+0x28, SEEK_SET) != offs+0x28) + || (read(dev, &label_read, LABEL_LEN) != LABEL_LEN)) + goto failure; + + close(dev); + if ((LOWORD(unicode_id) == 0x2f25) /* Unicode ID */ + && ((ver == 0x40) || (ver == 0x43) || (ver == 0x45))) + { /* yippee, unicode */ + int i; + WORD ch; + for (i=0; i Intel Unicode conversion :-\ */ + ch = label_read[i]; + label_read[i] = (ch << 8) | (ch >> 8); + } + WideCharToMultiByte( CP_ACP, 0, label_read, -1, label, 12, NULL, NULL ); + label[11] = 0; + } + else + { + strncpy(label, (LPSTR)label_read, 11); + label[11] = '\0'; + } + return 1; + } + } +failure: + close(dev); + ERR("error reading label !\n"); + return 0; +} + +/************************************************************************** + * CDROM_GetLabel [internal] + */ +static DWORD CDROM_GetLabel(int drive, char *label) +{ + HANDLE h = CDROM_Open(drive); + CDROM_DISK_DATA cdd; + DWORD br; + DWORD ret = 1; + + if (!h || !DeviceIoControl(h, IOCTL_CDROM_DISK_TYPE, NULL, 0, &cdd, sizeof(cdd), &br, 0)) + return 0; + + switch (cdd.DiskData & 0x03) + { + case CDROM_DISK_DATA_TRACK: + if (!CDROM_Data_GetLabel(drive, label)) + ret = 0; + case CDROM_DISK_AUDIO_TRACK: + strcpy(label, "Audio CD "); + break; + case CDROM_DISK_DATA_TRACK|CDROM_DISK_AUDIO_TRACK: + FIXME("Need to get the label of a mixed mode CD: not implemented yet !\n"); + /* fall through */ + case 0: + ret = 0; + break; + } + TRACE("CD: label is '%s'.\n", label); + + return ret; +} /*********************************************************************** * DRIVE_GetLabel */ @@ -605,6 +736,132 @@ const char * DRIVE_GetLabel( int drive ) DOSDrives[drive].label_read : DOSDrives[drive].label_conf; } +#define CDFRAMES_PERSEC 75 +#define CDFRAMES_PERMIN (CDFRAMES_PERSEC * 60) +#define FRAME_OF_ADDR(a) ((a)[0] * CDFRAMES_PERMIN + (a)[1] * CDFRAMES_PERSEC + (a)[2]) +#define FRAME_OF_TOC(toc, idx) FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address) + +/************************************************************************** + * CDROM_Audio_GetSerial [internal] + */ +static DWORD CDROM_Audio_GetSerial(HANDLE h) +{ + unsigned long serial = 0; + int i; + WORD wMagic; + DWORD dwStart, dwEnd, br; + CDROM_TOC toc; + + if (!DeviceIoControl(h, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, 0)) + return 0; + + /* + * wMagic collects the wFrames from track 1 + * dwStart, dwEnd collect the beginning and end of the disc respectively, in + * frames. + * There it is collected for correcting the serial when there are less than + * 3 tracks. + */ + wMagic = toc.TrackData[0].Address[2]; + dwStart = FRAME_OF_TOC(toc, toc.FirstTrack); + + for (i = 0; i <= toc.LastTrack - toc.FirstTrack; i++) { + serial += (toc.TrackData[i].Address[0] << 16) | + (toc.TrackData[i].Address[1] << 8) | toc.TrackData[i].Address[2]; + } + dwEnd = FRAME_OF_TOC(toc, toc.LastTrack + 1); + + if (toc.LastTrack - toc.FirstTrack + 1 < 3) + serial += wMagic + (dwEnd - dwStart); + + return serial; +} + +/************************************************************************** + * CDROM_Data_GetSerial [internal] + */ +static DWORD CDROM_Data_GetSerial(int drive) +{ + int dev = open(DOSDrives[drive].device, O_RDONLY|O_NONBLOCK); + WORD offs; + union { + unsigned long val; + unsigned char p[4]; + } serial; + BYTE b0 = 0, b1 = 1, b2 = 2, b3 = 3; + + + if (dev == -1) return 0; + offs = CDROM_Data_FindBestVoldesc(dev); + + serial.val = 0; + if (offs) + { + BYTE buf[2048]; + OSVERSIONINFOA ovi; + int i; + + lseek(dev, offs, SEEK_SET); + read(dev, buf, 2048); + /* + * OK, another braindead one... argh. Just believe it. + * Me$$ysoft chose to reverse the serial number in NT4/W2K. + * It's true and nobody will ever be able to change it. + */ + ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + GetVersionExA(&ovi); + if ((ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (ovi.dwMajorVersion >= 4)) + { + b0 = 3; b1 = 2; b2 = 1; b3 = 0; + } + for (i = 0; i < 2048; i += 4) + { + /* DON'T optimize this into DWORD !! (breaks overflow) */ + serial.p[b0] += buf[i+b0]; + serial.p[b1] += buf[i+b1]; + serial.p[b2] += buf[i+b2]; + serial.p[b3] += buf[i+b3]; + } + } + close(dev); + return serial.val; +} + +/************************************************************************** + * CDROM_GetSerial [internal] + */ +static DWORD CDROM_GetSerial(int drive) +{ + DWORD serial = 0; + HANDLE h = CDROM_Open(drive); + CDROM_DISK_DATA cdd; + DWORD br; + + if (!h || ! !DeviceIoControl(h, IOCTL_CDROM_DISK_TYPE, NULL, 0, &cdd, sizeof(cdd), &br, 0)) + return 0; + + switch (cdd.DiskData & 0x03) + { + case CDROM_DISK_DATA_TRACK: + /* hopefully a data CD */ + serial = CDROM_Data_GetSerial(drive); + break; + case CDROM_DISK_AUDIO_TRACK: + /* fall thru */ + case CDROM_DISK_DATA_TRACK|CDROM_DISK_AUDIO_TRACK: + serial = CDROM_Audio_GetSerial(h); + break; + case 0: + break; + } + + if (serial) + TRACE("CD serial number is %04x-%04x.\n", HIWORD(serial), LOWORD(serial)); + + CloseHandle(h); + + return serial; +} /*********************************************************************** * DRIVE_GetSerialNumber @@ -612,7 +869,7 @@ const char * DRIVE_GetLabel( int drive ) DWORD DRIVE_GetSerialNumber( int drive ) { DWORD serial = 0; -char buff[DRIVE_SUPER]; + char buff[DRIVE_SUPER]; if (!DRIVE_IsValid( drive )) return 0; @@ -938,7 +1195,7 @@ static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPSTR buf ) assert(s); ret = strlen(s) + 3; /* length of WHOLE current directory */ if (ret >= buflen) return ret + 1; - lstrcpynA( buf, "A:\\", min( 4, buflen ) ); + lstrcpynA( buf, "A:\\", min( 4u, buflen ) ); if (buflen) buf[0] += DRIVE_GetCurrentDrive(); if (buflen > 3) lstrcpynA( buf + 3, s, buflen - 3 ); return ret; diff --git a/files/file.c b/files/file.c index 06ea389c758..9cca77758bc 100644 --- a/files/file.c +++ b/files/file.c @@ -449,6 +449,11 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing, ret = FILE_OpenPipe(filename,access); goto done; } + else if (isalpha(filename[4]) && filename[5] == ':' && filename[6] == '\0') + { + ret = FILE_CreateDevice( (toupper(filename[4]) - 'A') | 0x20000, access, sa ); + goto done; + } else if (!DOSFS_GetDevice( filename )) { ret = DEVICE_Open( filename+4, access, sa ); diff --git a/include/cdrom.h b/include/cdrom.h deleted file mode 100644 index e7c42187689..00000000000 --- a/include/cdrom.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- tab-width: 8; c-basic-offset: 4 -*- */ -/* - * Header file for CD-ROM support - * - * Copyright 1994 Martin Ayotte - * Copyright 1999 Eric Pouech - * Copyright 2000 Andreas Mohr - */ - -#ifndef __WINE_CDROM_H__ -#define __WINE_CDROM_H__ - -#ifndef __WINE_CONFIG_H -# error You must include config.h to use this header -#endif - -#include -#include -#include "windef.h" -#include "wine/windef16.h" - -#ifdef HAVE_LINUX_CDROM_H -# include -#endif -#ifdef HAVE_LINUX_UCDROM_H -# include -#endif -#ifdef HAVE_SYS_CDIO_H -# include -#endif - -typedef struct { - const char *devname; -#if defined(linux) - struct cdrom_subchnl sc; -#elif defined(__FreeBSD__) || defined(__NetBSD__) - struct cd_sub_channel_info sc; -#endif - /* those data reflect the cdaudio structure and - * don't change while playing - */ - UINT16 nTracks; - UINT16 nFirstTrack; - UINT16 nLastTrack; - LPDWORD lpdwTrackLen; - LPDWORD lpdwTrackPos; - LPBYTE lpbTrackFlags; - DWORD dwFirstFrame; - DWORD dwLastFrame; - /* those data change while playing */ - int cdaMode; - UINT16 nCurTrack; - DWORD dwCurFrame; -} WINE_CDAUDIO; - -#define WINE_CDA_DONTKNOW 0x00 -#define WINE_CDA_NOTREADY 0x01 -#define WINE_CDA_OPEN 0x02 -#define WINE_CDA_PLAY 0x03 -#define WINE_CDA_STOP 0x04 -#define WINE_CDA_PAUSE 0x05 - -int CDROM_Open(WINE_CDAUDIO* wcda, int drive); -int CDROM_OpenDev(WINE_CDAUDIO* wcda); -int CDROM_GetMediaType(WINE_CDAUDIO* wcda, int parentdev); -int CDROM_CloseDev(int dev); -int CDROM_Close(WINE_CDAUDIO* wcda); -int CDROM_Reset(WINE_CDAUDIO* wcda, int parentdev); -int CDROM_Audio_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD stop, int parentdev); -int CDROM_Audio_Stop(WINE_CDAUDIO* wcda, int parentdev); -int CDROM_Audio_Pause(WINE_CDAUDIO* wcda, int pauseOn, int parentdev); -int CDROM_Audio_Seek(WINE_CDAUDIO* wcda, DWORD at, int parentdev); -int CDROM_SetDoor(WINE_CDAUDIO* wcda, int open, int parentdev); -UINT16 CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda, int parentdev); -BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda, int parentdev); -BOOL CDROM_Audio_GetCDStatus(WINE_CDAUDIO* wcda, int parentdev); -WORD CDROM_Data_FindBestVoldesc(int fd); -DWORD CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda); -DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda, int parentdev); -DWORD CDROM_GetSerial(int drive); -DWORD CDROM_GetLabel(int drive, char *label); - -#define CDFRAMES_PERSEC 75 -#define SECONDS_PERMIN 60 -#define CDFRAMES_PERMIN ((CDFRAMES_PERSEC) * (SECONDS_PERMIN)) - -#ifndef CDROM_DATA_TRACK -#define CDROM_DATA_TRACK 0x04 -#endif - -#define CDROM_MSF_MINUTE(msf) ((BYTE)(msf)) -#define CDROM_MSF_SECOND(msf) ((BYTE)(((WORD)(msf)) >> 8)) -#define CDROM_MSF_FRAME(msf) ((BYTE)((msf)>>16)) - -#define CDROM_MAKE_MSF(m, s, f) ((DWORD)(((BYTE)(m) | \ - ((WORD)(s)<<8)) | \ - (((DWORD)(BYTE)(f))<<16))) - -/* values borrowed from Linux 2.2.x cdrom.h */ -#define CDS_NO_INFO 0 -#define CDS_AUDIO 100 -#define CDS_DATA_1 101 -#define CDS_DATA_2 102 -#define CDS_XA_2_1 103 -#define CDS_XA_2_2 104 -#define CDS_MIXED 105 - -#endif - diff --git a/include/file.h b/include/file.h index 45a37d92ef1..815501efb04 100644 --- a/include/file.h +++ b/include/file.h @@ -115,4 +115,10 @@ extern int DOSFS_FindNext( const char *path, const char *short_mask, /* win32/device.c */ extern HANDLE DEVICE_Open( LPCSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); +/* ntdll/cdrom.c.c */ +extern BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode, + LPVOID lpInBuffer, DWORD nInBufferSize, + LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped); + #endif /* __WINE_FILE_H */ diff --git a/include/ntddcdrm.h b/include/ntddcdrm.h new file mode 100644 index 00000000000..cd3f3f3dea3 --- /dev/null +++ b/include/ntddcdrm.h @@ -0,0 +1,167 @@ +/* DDK information for CD ROM */ + +#ifndef __NTDDCDRM_H +#define __NTDDCDRM_H + +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_UNLOAD_DRIVER CTL_CODE(IOCTL_CDROM_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_CONTROL CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_PLAY_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_STOP_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_PAUSE_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RESUME_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define IOCTL_CDROM_DISK_TYPE CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_CHECK_VERIFY CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_EJECT_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_LOAD_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RESERVE CTL_CODE(IOCTL_CDROM_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RELEASE CTL_CODE(IOCTL_CDROM_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_FIND_NEW_DEVICES CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#include "ntddstor.h" + +#define MAXIMUM_NUMBER_TRACKS 100 +#define MAXIMUM_CDROM_SIZE 804 + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +} CDROM_TOC, *PCDROM_TOC; + +#define CDROM_TOC_SIZE sizeof(CDROM_TOC) + +typedef struct _CDROM_PLAY_AUDIO_MSF { + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; +} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + +typedef struct _CDROM_DISK_DATA { + ULONG DiskData; +} CDROM_DISK_DATA, *PCDROM_DISK_DATA; + +#define CDROM_DISK_AUDIO_TRACK (0x00000001) +#define CDROM_DISK_DATA_TRACK (0x00000002) + +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval : 1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 + +#define ADR_NO_MODE_INFORMATION 0x0 +#define ADR_ENCODES_CURRENT_POSITION 0x1 +#define ADR_ENCODES_MEDIA_CATALOG 0x2 +#define ADR_ENCODES_ISRC 0x3 + +#define AUDIO_WITH_PREEMPHASIS 0x0 +#define DIGITAL_COPY_PERMITTED 0x2 +#define AUDIO_DATA_TRACK 0x4 +#define TWO_FOUR_CHANNEL_AUDIO 0x8 + +typedef struct _CDROM_AUDIO_CONTROL { + UCHAR LbaFormat; + USHORT LogicalBlocksPerSecond; +} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; + +typedef struct _VOLUME_CONTROL { + UCHAR PortVolume[4]; +} VOLUME_CONTROL, *PVOLUME_CONTROL; + +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; + +#endif /* __NTDDCDRM_H */ diff --git a/include/ntddstor.h b/include/ntddstor.h new file mode 100644 index 00000000000..cbc9b5d2214 --- /dev/null +++ b/include/ntddstor.h @@ -0,0 +1,229 @@ +/* DDK definitions for storage media access */ + +#ifndef _NTDDSTOR_H_ +#define _NTDDSTOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE + +#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_GET_MEDIA_TYPES CTL_CODE(IOCTL_STORAGE_BASE, 0x0300, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_GET_DEVICE_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) + +typedef struct _STORAGE_DEVICE_NUMBER { + DEVICE_TYPE DeviceType; + ULONG DeviceNumber; + ULONG PartitionNumber; +} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER; + +typedef struct _STORAGE_BUS_RESET_REQUEST { + UCHAR PathId; +} STORAGE_BUS_RESET_REQUEST, *PSTORAGE_BUS_RESET_REQUEST; + +typedef struct _PREVENT_MEDIA_REMOVAL { + BOOLEAN PreventMediaRemoval; +} PREVENT_MEDIA_REMOVAL, *PPREVENT_MEDIA_REMOVAL; + +typedef struct _TAPE_STATISTICS { + ULONG Version; + ULONG Flags; + LARGE_INTEGER RecoveredWrites; + LARGE_INTEGER UnrecoveredWrites; + LARGE_INTEGER RecoveredReads; + LARGE_INTEGER UnrecoveredReads; + UCHAR CompressionRatioReads; + UCHAR CompressionRatioWrites; +} TAPE_STATISTICS, *PTAPE_STATISTICS; + +#define RECOVERED_WRITES_VALID 0x00000001 +#define UNRECOVERED_WRITES_VALID 0x00000002 +#define RECOVERED_READS_VALID 0x00000004 +#define UNRECOVERED_READS_VALID 0x00000008 +#define WRITE_COMPRESSION_INFO_VALID 0x00000010 +#define READ_COMPRESSION_INFO_VALID 0x00000020 + +typedef struct _TAPE_GET_STATISTICS { + ULONG Operation; +} TAPE_GET_STATISTICS, *PTAPE_GET_STATISTICS; + +#define TAPE_RETURN_STATISTICS 0L +#define TAPE_RETURN_ENV_INFO 1L +#define TAPE_RESET_STATISTICS 2L + +typedef enum _STORAGE_MEDIA_TYPE { + /* see also defines in ntdddisk.h */ + + DDS_4mm = 0x20, + MiniQic, + Travan, + QIC, + MP_8mm, + AME_8mm, + AIT1_8mm, + DLT, + NCTP, + IBM_3480, + IBM_3490E, + IBM_Magstar_3590, + IBM_Magstar_MP, + STK_DATA_D3, + SONY_DTF, + DV_6mm, + DMI, + SONY_D2, + CLEANER_CARTRIDGE, + CD_ROM, + CD_R, + CD_RW, + DVD_ROM, + DVD_R, + DVD_RW, + MO_3_RW, + MO_5_WO, + MO_5_RW, + MO_5_LIMDOW, + PC_5_WO, + PC_5_RW, + PD_5_RW, + ABL_5_WO, + PINNACLE_APEX_5_RW, + SONY_12_WO, + PHILIPS_12_WO, + HITACHI_12_WO, + CYGNET_12_WO, + KODAK_14_WO, + MO_NFR_525, + NIKON_12_RW, + IOMEGA_ZIP, + IOMEGA_JAZ, + SYQUEST_EZ135, + SYQUEST_EZFLYER, + SYQUEST_SYJET, + AVATAR_F2, + MP2_8mm +} STORAGE_MEDIA_TYPE, *PSTORAGE_MEDIA_TYPE; + +#define MEDIA_ERASEABLE 0x00000001 +#define MEDIA_WRITE_ONCE 0x00000002 +#define MEDIA_READ_ONLY 0x00000004 +#define MEDIA_READ_WRITE 0x00000008 +#define MEDIA_WRITE_PROTECTED 0x00000100 +#define MEDIA_CURRENTLY_MOUNTED 0x80000000 + +typedef struct _DEVICE_MEDIA_INFO { + union { + struct { + LARGE_INTEGER Cylinders; + STORAGE_MEDIA_TYPE MediaType; + ULONG TracksPerCylinder; + ULONG SectorsPerTrack; + ULONG BytesPerSector; + ULONG NumberMediaSides; + ULONG MediaCharacteristics; + } DiskInfo; + struct { + LARGE_INTEGER Cylinders; + STORAGE_MEDIA_TYPE MediaType; + ULONG TracksPerCylinder; + ULONG SectorsPerTrack; + ULONG BytesPerSector; + ULONG NumberMediaSides; + ULONG MediaCharacteristics; + } RemovableDiskInfo; + struct { + STORAGE_MEDIA_TYPE MediaType; + ULONG MediaCharacteristics; + ULONG CurrentBlockSize; + } TapeInfo; + } DeviceSpecific; +} DEVICE_MEDIA_INFO, *PDEVICE_MEDIA_INFO; + +typedef struct _GET_MEDIA_TYPES { + ULONG DeviceType; + ULONG MediaInfoCount; + DEVICE_MEDIA_INFO MediaInfo[1]; +} GET_MEDIA_TYPES, *PGET_MEDIA_TYPES; + +typedef enum _STORAGE_QUERY_TYPE { + PropertyStandardQuery = 0, + PropertyExistsQuery, + PropertyMaskQuery, + PropertyQueryMaxDefined +} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; + +typedef enum _STORAGE_PROPERTY_ID { + StorageDeviceProperty = 0, + StorageAdapterProperty +} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; + +typedef struct _STORAGE_PROPERTY_QUERY { + STORAGE_PROPERTY_ID PropertyId; + STORAGE_QUERY_TYPE QueryType; + UCHAR AdditionalParameters[1]; +} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; + +typedef struct _STORAGE_DESCRIPTOR_HEADER { + ULONG Version; + ULONG Size; +} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER; + +typedef enum _STORAGE_BUS_TYPE { + BusTypeUnknown = 0x00, + BusTypeScsi, + BusTypeAtapi, + BusTypeAta, + BusType1394, + BusTypeSsa, + BusTypeFibre, + BusTypeMaxReserved = 0x7F +} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; + +typedef struct _STORAGE_DEVICE_DESCRIPTOR { + ULONG Version; + ULONG Size; + UCHAR DeviceType; + UCHAR DeviceTypeModifier; + BOOLEAN RemovableMedia; + BOOLEAN CommandQueueing; + ULONG VendorIdOffset; + ULONG ProductIdOffset; + ULONG ProductRevisionOffset; + ULONG SerialNumberOffset; + STORAGE_BUS_TYPE BusType; + ULONG RawPropertiesLength; + UCHAR RawDeviceProperties[1]; +} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; + +typedef struct _STORAGE_ADAPTER_DESCRIPTOR { + ULONG Version; + ULONG Size; + ULONG MaximumTransferLength; + ULONG MaximumPhysicalPages; + ULONG AlignmentMask; + BOOLEAN AdapterUsesPio; + BOOLEAN AdapterScansDown; + BOOLEAN CommandQueueing; + BOOLEAN AcceleratedTransfer; + BOOLEAN BusType; + USHORT BusMajorVersion; + USHORT BusMinorVersion; +} STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR; + +#ifdef __cplusplus +} +#endif + +#endif /* _NTDDSTOR_H_ */ diff --git a/include/winioctl.h b/include/winioctl.h index d7a3d718d84..8ac269fd51d 100644 --- a/include/winioctl.h +++ b/include/winioctl.h @@ -150,7 +150,9 @@ #define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) - +#define IOCTL_STORAGE_EJECTION_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0250, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MCN_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0251, METHOD_BUFFERED, FILE_ANY_ACCESS) + #define IOCTL_STORAGE_GET_MEDIA_TYPES CTL_CODE(IOCTL_STORAGE_BASE, 0x0300, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_STORAGE_GET_MEDIA_TYPES_EX CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS) @@ -213,6 +215,81 @@ #define PARTITION_LDM 0x42 /* Logical Disk Manager partition */ #define PARTITION_UNIX 0x63 /* Unix */ +typedef enum _MEDIA_TYPE { + Unknown, F5_1Pt2_512, F3_1Pt44_512, F3_2Pt88_512, F3_20Pt8_512, F3_720_512, F5_360_512, + F5_320_512, F5_320_1024, F5_180_512, F5_160_512, RemovableMedia, FixedMedia, F3_120M_512, + F3_640_512, F5_640_512, F5_720_512, F3_1Pt2_512, F3_1Pt23_1024, F5_1Pt23_1024, F3_128Mb_512, + F3_230Mb_512, F8_256_128 +} MEDIA_TYPE, *PMEDIA_TYPE; + +typedef struct _FORMAT_PARAMETERS { + MEDIA_TYPE MediaType; + DWORD StartCylinderNumber; + DWORD EndCylinderNumber; + DWORD StartHeadNumber; + DWORD EndHeadNumber; +} FORMAT_PARAMETERS, *PFORMAT_PARAMETERS; + +typedef WORD BAD_TRACK_NUMBER; +typedef WORD *PBAD_TRACK_NUMBER; + +typedef struct _FORMAT_EX_PARAMETERS { + MEDIA_TYPE MediaType; + DWORD StartCylinderNumber; + DWORD EndCylinderNumber; + DWORD StartHeadNumber; + DWORD EndHeadNumber; + WORD FormatGapLength; + WORD SectorsPerTrack; + WORD SectorNumber[1]; +} FORMAT_EX_PARAMETERS, *PFORMAT_EX_PARAMETERS; + +typedef struct _DISK_GEOMETRY { + LARGE_INTEGER Cylinders; + MEDIA_TYPE MediaType; + DWORD TracksPerCylinder; + DWORD SectorsPerTrack; + DWORD BytesPerSector; +} DISK_GEOMETRY, *PDISK_GEOMETRY; + +typedef struct _PARTITION_INFORMATION { + LARGE_INTEGER StartingOffset; + LARGE_INTEGER PartitionLength; + DWORD HiddenSectors; + DWORD PartitionNumber; + BYTE PartitionType; + BOOLEAN BootIndicator; + BOOLEAN RecognizedPartition; + BOOLEAN RewritePartition; +} PARTITION_INFORMATION, *PPARTITION_INFORMATION; + +typedef struct _SET_PARTITION_INFORMATION { + BYTE PartitionType; +} SET_PARTITION_INFORMATION, *PSET_PARTITION_INFORMATION; + +typedef struct _DRIVE_LAYOUT_INFORMATION { + DWORD PartitionCount; + DWORD Signature; + PARTITION_INFORMATION PartitionEntry[1]; +} DRIVE_LAYOUT_INFORMATION, *PDRIVE_LAYOUT_INFORMATION; + +typedef struct _VERIFY_INFORMATION { + LARGE_INTEGER StartingOffset; + DWORD Length; +} VERIFY_INFORMATION, *PVERIFY_INFORMATION; + +typedef struct _REASSIGN_BLOCKS { + WORD Reserved; + WORD Count; + DWORD BlockNumber[1]; +} REASSIGN_BLOCKS, *PREASSIGN_BLOCKS; + +#if(_WIN32_WINNT >= 0x0400) +typedef struct _DISK_CONTROLLER_NUMBER { + DWORD ControllerNumber; + DWORD DiskNumber; +} DISK_CONTROLLER_NUMBER, *PDISK_CONTROLLER_NUMBER; +#endif /* _WIN32_WINNT >= 0x0400 */ /* Device Io Stuff - Most VxD support. * NOTE: All VxD messages seem to start with a hiword or 0 diff --git a/misc/Makefile.in b/misc/Makefile.in index 5565a0df2bf..2ebc27672cc 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -7,7 +7,6 @@ VPATH = @srcdir@ MODULE = misc C_SRCS = \ - cdrom.c \ cpu.c \ error.c \ main.c \ diff --git a/misc/cdrom.c b/misc/cdrom.c deleted file mode 100644 index ec89b8a7adf..00000000000 --- a/misc/cdrom.c +++ /dev/null @@ -1,908 +0,0 @@ -/* -*- tab-width: 8; c-basic-offset: 4 -*- */ -/* - * Main file for CD-ROM support - * - * Copyright 1994 Martin Ayotte - * Copyright 1999 Eric Pouech - * Copyright 2000 Andreas Mohr - */ - -#include "config.h" - -#include -#include -#include -#include -#include "winnls.h" -#include "cdrom.h" -#include "drive.h" -#include "debugtools.h" -#include "winbase.h" - -DEFAULT_DEBUG_CHANNEL(cdrom); - -#define MAX_CDAUDIO_TRACKS 256 - -#define CDROM_OPEN(wcda,parentdev) \ - (((parentdev) == -1) ? CDROM_OpenDev(wcda) : (parentdev)) - -#define CDROM_CLOSE(dev,parentdev) \ - (((parentdev) == -1) ? CDROM_CloseDev(dev) : 0) - -/************************************************************************** - * CDROM_Open [internal] - * - * drive = 0, 1, ... - * or -1 (figure it out) - */ -int CDROM_Open(WINE_CDAUDIO* wcda, int drive) -{ - int i, dev; - BOOL avail = FALSE; - - if (drive == -1) - { - char root[] = "A:\\"; - for (i=0; i < MAX_DOS_DRIVES; i++, root[0]++) - if (GetDriveTypeA(root) == DRIVE_CDROM) - { - drive = i; - avail = TRUE; - break; - } - } - else - avail = TRUE; - - if (avail == FALSE) - { - WARN("No CD-ROM #%d found !\n", drive); - return -1; - } - if ((wcda->devname = DRIVE_GetDevice(drive)) == NULL) -{ - WARN("No device entry for CD-ROM #%d (drive %c:) found !\n", - drive, 'A' + drive); - return -1; - } - - /* Test whether device can be opened */ - dev = CDROM_OpenDev(wcda); - if (dev == -1) - return -1; - else - CDROM_CloseDev(dev); - - wcda->cdaMode = WINE_CDA_OPEN; /* to force reading tracks info */ - wcda->nCurTrack = 0; - wcda->nTracks = 0; - wcda->dwFirstFrame = 0; - wcda->dwLastFrame = 0; - wcda->lpdwTrackLen = NULL; - wcda->lpdwTrackPos = NULL; - wcda->lpbTrackFlags = NULL; - TRACE("opened drive %c: (device %s)\n", 'A' + drive, wcda->devname); - return 0; -} - -/************************************************************************** - * CDROM_OpenDev [internal] - * - */ -int CDROM_OpenDev(WINE_CDAUDIO* wcda) -{ - int dev = open(wcda->devname, O_RDONLY | O_NONBLOCK, 0); - if (dev == -1) - WARN("can't open device '%s'! (%s)\n", wcda->devname, strerror(errno)); - - TRACE("-> %d\n", dev); - return dev; -} - -/************************************************************************** - * CDROM_GetMediaType [internal] - */ -int CDROM_GetMediaType(WINE_CDAUDIO* wcda, int parentdev) -{ - int type = -1; -#ifdef linux - int dev = CDROM_OPEN( wcda, parentdev ); - type = ioctl(dev, CDROM_DISC_STATUS); - CDROM_CLOSE( dev, parentdev ); -#endif - TRACE("-> %d\n", type); - return type; -} - -/************************************************************************** - * CDROM_Close [internal] - */ -int CDROM_CloseDev(int dev) -{ - TRACE("%d\n", dev); - return close(dev); -} - -/************************************************************************** - * CDROM_Close [internal] - */ -int CDROM_Close(WINE_CDAUDIO* wcda) -{ -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - if (wcda->lpdwTrackLen != NULL) free(wcda->lpdwTrackLen); - if (wcda->lpdwTrackPos != NULL) free(wcda->lpdwTrackPos); - if (wcda->lpbTrackFlags != NULL) free(wcda->lpbTrackFlags); - TRACE("%s\n", wcda->devname); - return 0; -#else - return -1; -#endif -} - -/************************************************************************** - * CDROM_Get_UPC [internal] - * - * upc has to be 14 bytes long - */ -int CDROM_Get_UPC(WINE_CDAUDIO* wcda, LPSTR upc, int parentdev) -{ -#ifdef linux - struct cdrom_mcn mcn; - int dev = CDROM_OPEN( wcda, parentdev ); - int status = ioctl(dev, CDROM_GET_MCN, &mcn); - CDROM_CLOSE( dev, parentdev ); - if (status) -{ - ERR("ioctl() failed with code %d\n",status); - return -1; - } - strcpy(upc, mcn.medium_catalog_number); - return 0; -#else - return -1; -#endif -} - -/************************************************************************** - * CDROM_Audio_GetNumberOfTracks [internal] - */ -UINT16 CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda, int parentdev) -{ - UINT16 ret = (UINT16)-1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) -#ifdef linux - struct cdrom_tochdr hdr; -#else - struct ioc_toc_header hdr; -#endif - int dev = CDROM_OPEN( wcda, parentdev ); - - if (wcda->nTracks == 0) { -#ifdef linux - if (ioctl(dev, CDROMREADTOCHDR, &hdr)) -#else - if (ioctl(dev, CDIOREADTOCHEADER, &hdr)) -#endif - { - WARN("(%p) -- Error occurred (%s)!\n", wcda, strerror(errno)); - goto end; - } -#ifdef linux - wcda->nFirstTrack = hdr.cdth_trk0; - wcda->nLastTrack = hdr.cdth_trk1; -#else - wcda->nFirstTrack = hdr.starting_track; - wcda->nLastTrack = hdr.ending_track; -#endif - wcda->nTracks = wcda->nLastTrack - wcda->nFirstTrack + 1; - } - ret = wcda->nTracks; -end: - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Audio_GetTracksInfo [internal] - */ -BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda, int parentdev) -{ - BOOL ret = FALSE; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int i, length; - int start, last_start = 0; - int total_length = 0; -#ifdef linux - struct cdrom_tocentry entry; -#else - struct ioc_read_toc_entry entry; - struct cd_toc_entry toc_buffer; -#endif - int dev = CDROM_OPEN( wcda, parentdev ); - - if (wcda->nTracks == 0) { - if (CDROM_Audio_GetNumberOfTracks(wcda, dev) == (WORD)-1) - goto end; - } - TRACE("nTracks=%u\n", wcda->nTracks); - - if (wcda->lpdwTrackLen != NULL) - free(wcda->lpdwTrackLen); - wcda->lpdwTrackLen = (LPDWORD)malloc((wcda->nTracks + 1) * sizeof(DWORD)); - if (wcda->lpdwTrackPos != NULL) - free(wcda->lpdwTrackPos); - wcda->lpdwTrackPos = (LPDWORD)malloc((wcda->nTracks + 1) * sizeof(DWORD)); - if (wcda->lpbTrackFlags != NULL) - free(wcda->lpbTrackFlags); - wcda->lpbTrackFlags = (LPBYTE)malloc((wcda->nTracks + 1) * sizeof(BYTE)); - if (wcda->lpdwTrackLen == NULL || wcda->lpdwTrackPos == NULL || - wcda->lpbTrackFlags == NULL) { - WARN("error allocating track table !\n"); - goto end; - } - memset(wcda->lpdwTrackLen, 0, (wcda->nTracks + 1) * sizeof(DWORD)); - memset(wcda->lpdwTrackPos, 0, (wcda->nTracks + 1) * sizeof(DWORD)); - memset(wcda->lpbTrackFlags, 0, (wcda->nTracks + 1) * sizeof(BYTE)); - for (i = 0; i <= wcda->nTracks; i++) { - if (i == wcda->nTracks) -#ifdef linux - entry.cdte_track = CDROM_LEADOUT; -#else -#define LEADOUT 0xaa - entry.starting_track = LEADOUT; /* FIXME */ -#endif - else -#ifdef linux - entry.cdte_track = i + 1; -#else - entry.starting_track = i + 1; -#endif -#ifdef linux - entry.cdte_format = CDROM_MSF; -#else - memset((char *)&toc_buffer, 0, sizeof(toc_buffer)); - entry.address_format = CD_MSF_FORMAT; - entry.data_len = sizeof(toc_buffer); - entry.data = &toc_buffer; -#endif -#ifdef linux - if (ioctl(dev, CDROMREADTOCENTRY, &entry)) -#else - if (ioctl(dev, CDIOREADTOCENTRYS, &entry)) -#endif - { - WARN("error read entry (%s)\n", strerror(errno)); - /* update status according to new status */ - CDROM_Audio_GetCDStatus(wcda, dev); - - goto end; - } -#ifdef linux - start = CDFRAMES_PERSEC * (SECONDS_PERMIN * - entry.cdte_addr.msf.minute + entry.cdte_addr.msf.second) + - entry.cdte_addr.msf.frame; -#else - start = CDFRAMES_PERSEC * (SECONDS_PERMIN * - toc_buffer.addr.msf.minute + toc_buffer.addr.msf.second) + - toc_buffer.addr.msf.frame; -#endif - if (i == 0) { - last_start = start; - wcda->dwFirstFrame = start; - TRACE("dwFirstOffset=%u\n", start); - } else { - length = start - last_start; - last_start = start; - start = last_start - length; - total_length += length; - wcda->lpdwTrackLen[i - 1] = length; - wcda->lpdwTrackPos[i - 1] = start; - TRACE("track #%u start=%u len=%u\n", i, start, length); - } -#ifdef linux - wcda->lpbTrackFlags[i] = - (entry.cdte_adr << 4) | (entry.cdte_ctrl & 0x0f); -#else - wcda->lpbTrackFlags[i] = - (toc_buffer.addr_type << 4) | (toc_buffer.control & 0x0f); -#endif - TRACE("track #%u flags=%02x\n", i + 1, wcda->lpbTrackFlags[i]); - } - wcda->dwLastFrame = last_start; - TRACE("total_len=%u\n", total_length); - ret = TRUE; -end: - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Audio_GetCDStatus [internal] - */ -BOOL CDROM_Audio_GetCDStatus(WINE_CDAUDIO* wcda, int parentdev) -{ -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int oldmode = wcda->cdaMode; - int ret = FALSE; - int dev = CDROM_OPEN( wcda, parentdev ); -#ifdef linux - wcda->sc.cdsc_format = CDROM_MSF; -#else - struct ioc_read_subchannel read_sc; - - read_sc.address_format = CD_MSF_FORMAT; - read_sc.data_format = CD_CURRENT_POSITION; - read_sc.track = 0; - read_sc.data_len = sizeof(wcda->sc); - read_sc.data = (struct cd_sub_channel_info *)&wcda->sc; -#endif -#ifdef linux - if (ioctl(dev, CDROMSUBCHNL, &wcda->sc)) -#else - if (ioctl(dev, CDIOCREADSUBCHANNEL, &read_sc)) -#endif - { - TRACE("opened or no_media (%s)!\n", strerror(errno)); - wcda->cdaMode = WINE_CDA_OPEN; /* was NOT_READY */ - goto end; - } - switch ( -#ifdef linux - wcda->sc.cdsc_audiostatus -#else - wcda->sc.header.audio_status -#endif - ) { -#ifdef linux - case CDROM_AUDIO_INVALID: -#else - case CD_AS_AUDIO_INVALID: -#endif - /* seems that this means stop for ide drives */ - wcda->cdaMode = WINE_CDA_STOP; - TRACE("AUDIO_INVALID -> WINE_CDA_STOP\n"); - break; -#ifdef linux - case CDROM_AUDIO_NO_STATUS: -#else - case CD_AS_NO_STATUS: -#endif - wcda->cdaMode = WINE_CDA_STOP; - TRACE("WINE_CDA_STOP !\n"); - break; -#ifdef linux - case CDROM_AUDIO_PLAY: -#else - case CD_AS_PLAY_IN_PROGRESS: -#endif - wcda->cdaMode = WINE_CDA_PLAY; - break; -#ifdef linux - case CDROM_AUDIO_PAUSED: -#else - case CD_AS_PLAY_PAUSED: -#endif - wcda->cdaMode = WINE_CDA_PAUSE; - TRACE("WINE_CDA_PAUSE !\n"); - break; - default: -#ifdef linux - TRACE("status=%02X !\n", - wcda->sc.cdsc_audiostatus); -#else - TRACE("status=%02X !\n", - wcda->sc.header.audio_status); -#endif - } -#ifdef linux - wcda->nCurTrack = wcda->sc.cdsc_trk; - wcda->dwCurFrame = - CDFRAMES_PERMIN * wcda->sc.cdsc_absaddr.msf.minute + - CDFRAMES_PERSEC * wcda->sc.cdsc_absaddr.msf.second + - wcda->sc.cdsc_absaddr.msf.frame; -#else - wcda->nCurTrack = wcda->sc.what.position.track_number; - wcda->dwCurFrame = - CDFRAMES_PERMIN * wcda->sc.what.position.absaddr.msf.minute + - CDFRAMES_PERSEC * wcda->sc.what.position.absaddr.msf.second + - wcda->sc.what.position.absaddr.msf.frame; -#endif -#ifdef linux - TRACE("%02u-%02u:%02u:%02u\n", - wcda->sc.cdsc_trk, - wcda->sc.cdsc_absaddr.msf.minute, - wcda->sc.cdsc_absaddr.msf.second, - wcda->sc.cdsc_absaddr.msf.frame); -#else - TRACE("%02u-%02u:%02u:%02u\n", - wcda->sc.what.position.track_number, - wcda->sc.what.position.absaddr.msf.minute, - wcda->sc.what.position.absaddr.msf.second, - wcda->sc.what.position.absaddr.msf.frame); -#endif - - if (oldmode != wcda->cdaMode && oldmode == WINE_CDA_OPEN) { - if (!CDROM_Audio_GetTracksInfo(wcda, dev)) { - WARN("error updating TracksInfo !\n"); - goto end; - } - } - if (wcda->cdaMode != WINE_CDA_OPEN) - ret = TRUE; -end: - CDROM_CLOSE( dev, parentdev ); - return ret; -#else - return FALSE; -#endif -} - -/************************************************************************** - * CDROM_Audio_Play [internal] - */ -int CDROM_Audio_Play(WINE_CDAUDIO* wcda, DWORD start, DWORD end, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) -#ifdef linux - struct cdrom_msf msf; -#else - struct ioc_play_msf msf; -#endif - int dev = CDROM_OPEN( wcda, parentdev ); - -#ifdef linux - msf.cdmsf_min0 = start / CDFRAMES_PERMIN; - msf.cdmsf_sec0 = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; - msf.cdmsf_frame0 = start % CDFRAMES_PERSEC; - msf.cdmsf_min1 = end / CDFRAMES_PERMIN; - msf.cdmsf_sec1 = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; - msf.cdmsf_frame1 = end % CDFRAMES_PERSEC; -#else - msf.start_m = start / CDFRAMES_PERMIN; - msf.start_s = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; - msf.start_f = start % CDFRAMES_PERSEC; - msf.end_m = end / CDFRAMES_PERMIN; - msf.end_s = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; - msf.end_f = end % CDFRAMES_PERSEC; -#endif -#ifdef linux - if (ioctl(dev, CDROMSTART)) -#else - if (ioctl(dev, CDIOCSTART, NULL)) -#endif - { - WARN("motor doesn't start !\n"); - goto end; - } -#ifdef linux - if (ioctl(dev, CDROMPLAYMSF, &msf)) -#else - if (ioctl(dev, CDIOCPLAYMSF, &msf)) -#endif - { - WARN("device doesn't play !\n"); - goto end; - } -#ifdef linux - TRACE("msf = %d:%d:%d %d:%d:%d\n", - msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0, - msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1); -#else - TRACE("msf = %d:%d:%d %d:%d:%d\n", - msf.start_m, msf.start_s, msf.start_f, - msf.end_m, msf.end_s, msf.end_f); -#endif - ret = 0; -end: - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Audio_Stop [internal] - */ -int CDROM_Audio_Stop(WINE_CDAUDIO* wcda, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int dev = CDROM_OPEN( wcda, parentdev ); -#ifdef linux - ret = ioctl(dev, CDROMSTOP); -#else - ret = ioctl(dev, CDIOCSTOP, NULL); -#endif - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Audio_Pause [internal] - */ -int CDROM_Audio_Pause(WINE_CDAUDIO* wcda, int pauseOn, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int dev = CDROM_OPEN( wcda, parentdev ); -#ifdef linux - ret = ioctl(dev, pauseOn ? CDROMPAUSE : CDROMRESUME); -#else - ret = ioctl(dev, pauseOn ? CDIOCPAUSE : CDIOCRESUME, NULL); -#endif - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Audio_Seek [internal] - */ -int CDROM_Audio_Seek(WINE_CDAUDIO* wcda, DWORD at, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int dev = CDROM_OPEN( wcda, parentdev ); -#ifdef linux - struct cdrom_msf0 msf; - msf.minute = at / CDFRAMES_PERMIN; - msf.second = (at % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; - msf.frame = at % CDFRAMES_PERSEC; - - ret = ioctl(dev, CDROMSEEK, &msf); -#else - /* FIXME: the current end for play is lost - * use end of CD ROM instead - */ - FIXME("Could a BSD expert implement the seek function ?\n"); - CDROM_Audio_Play(wcda, at, wcda->lpdwTrackPos[wcda->nTracks] + wcda->lpdwTrackLen[wcda->nTracks], dev); -#endif - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_SetDoor [internal] - */ -int CDROM_SetDoor(WINE_CDAUDIO* wcda, int open, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int dev = CDROM_OPEN( wcda, parentdev ); - - TRACE("%d\n", open); -#ifdef linux - if (open) { - ret = ioctl(dev, CDROMEJECT); - } else { - ret = ioctl(dev, CDROMCLOSETRAY); - } -#else - ret = (ioctl(dev, CDIOCALLOW, NULL)) || - (ioctl(dev, open ? CDIOCEJECT : CDIOCCLOSE, NULL)) || - (ioctl(dev, CDIOCPREVENT, NULL)); -#endif - wcda->nTracks = 0; - if (ret == -1) - WARN("failed (%s)\n", strerror(errno)); - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Reset [internal] - */ -int CDROM_Reset(WINE_CDAUDIO* wcda, int parentdev) -{ - int ret = -1; -#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) - int dev = CDROM_OPEN( wcda, parentdev ); -#ifdef linux - ret = ioctl(dev, CDROMRESET); -#else - ret = ioctl(dev, CDIOCRESET, NULL); -#endif - CDROM_CLOSE( dev, parentdev ); -#endif - return ret; -} - -/************************************************************************** - * CDROM_Data_FindBestVoldesc [internal] - */ -WORD CDROM_Data_FindBestVoldesc(int fd) -{ - BYTE cur_vd_type, max_vd_type = 0; - unsigned int offs, best_offs=0, extra_offs = 0; - char sig[3]; - - - for (offs=0x8000; offs <= 0x9800; offs += 0x800) - { - /* if 'CDROM' occurs at position 8, this is a pre-iso9660 cd, and - * the volume label is displaced forward by 8 - */ - lseek(fd, offs+11, SEEK_SET); /* check for non-ISO9660 signature */ - read(fd, &sig, 3); - if ((sig[0]=='R')&&(sig[1]=='O')&&(sig[2]=='M')) - { - extra_offs=8; - } - lseek(fd, offs+extra_offs, SEEK_SET); - read(fd, &cur_vd_type, 1); - if (cur_vd_type == 0xff) /* voldesc set terminator */ - break; - if (cur_vd_type > max_vd_type) - { - max_vd_type = cur_vd_type; - best_offs = offs + extra_offs; - } - } - return best_offs; -} - -/************************************************************************** - * CDROM_Audio_GetSerial [internal] - */ -DWORD CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda) -{ - unsigned long serial = 0; - int i; - DWORD dwFrame, msf; - WORD wMinutes, wSeconds, wFrames; - WORD wMagic; - DWORD dwStart, dwEnd; - - /* - * wMagic collects the wFrames from track 1 - * dwStart, dwEnd collect the beginning and end of the disc respectively, in - * frames. - * There it is collected for correcting the serial when there are less than - * 3 tracks. - */ - wMagic = 0; - dwStart = dwEnd = 0; - - for (i = 0; i < wcda->nTracks; i++) { - dwFrame = wcda->lpdwTrackPos[i]; - wMinutes = dwFrame / CDFRAMES_PERMIN; - wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC; - wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds; - msf = CDROM_MAKE_MSF(wMinutes, wSeconds, wFrames); - - serial += (CDROM_MSF_MINUTE(msf) << 16) + - (CDROM_MSF_SECOND(msf) << 8) + - (CDROM_MSF_FRAME(msf)); - - if (i==0) - { - wMagic = wFrames; - dwStart = dwFrame; - } - dwEnd = dwFrame + wcda->lpdwTrackLen[i]; - - } - - if (wcda->nTracks < 3) - { - serial += wMagic + (dwEnd - dwStart); - } - return serial; -} - -/************************************************************************** - * CDROM_Data_GetSerial [internal] - */ -DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda, int parentdev) -{ - int dev = CDROM_OPEN( wcda, parentdev ); - WORD offs = CDROM_Data_FindBestVoldesc(dev); - union { - unsigned long val; - unsigned char p[4]; - } serial; - BYTE b0 = 0, b1 = 1, b2 = 2, b3 = 3; - - serial.val = 0; - if (offs) - { - BYTE buf[2048]; - OSVERSIONINFOA ovi; - int i; - - lseek(dev,offs,SEEK_SET); - read(dev,buf,2048); - /* - * OK, another braindead one... argh. Just believe it. - * Me$$ysoft chose to reverse the serial number in NT4/W2K. - * It's true and nobody will ever be able to change it. - */ - ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - GetVersionExA(&ovi); - if ((ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) - && (ovi.dwMajorVersion >= 4)) - { - b0 = 3; b1 = 2; b2 = 1; b3 = 0; - } - for(i=0; i<2048; i+=4) - { - /* DON'T optimize this into DWORD !! (breaks overflow) */ - serial.p[b0] += buf[i+b0]; - serial.p[b1] += buf[i+b1]; - serial.p[b2] += buf[i+b2]; - serial.p[b3] += buf[i+b3]; - } - } - CDROM_CLOSE( dev, parentdev ); - return serial.val; -} - -/************************************************************************** - * CDROM_GetSerial [internal] - */ -DWORD CDROM_GetSerial(int drive) -{ - WINE_CDAUDIO wcda; - DWORD serial = 0; - - /* EXPIRES 01.01.2002 */ - WARN("CD-ROM serial number calculation might fail.\n"); - WARN("Please test with as many exotic CDs as possible !\n"); - - if (!(CDROM_Open(&wcda, drive))) - { - int dev = CDROM_OpenDev(&wcda); - int media = CDROM_GetMediaType(&wcda, dev); - - switch (media) - { - case CDS_AUDIO: - case CDS_MIXED: /* mixed is basically a mountable audio CD */ - if (!(CDROM_Audio_GetCDStatus(&wcda, dev))) { - ERR("couldn't get CD status !\n"); - goto end; - } - serial = CDROM_Audio_GetSerial(&wcda); - break; - case CDS_DATA_1: - case CDS_DATA_2: - case CDS_XA_2_1: - case CDS_XA_2_2: - case -1: /* ioctl() error: ISO9660 image file given ? */ - /* hopefully a data CD */ - serial = CDROM_Data_GetSerial(&wcda, dev); - break; - default: - WARN("Strange CD type (%d) or empty ?\n", media); - } - if (serial) - TRACE("CD serial number is %04x-%04x.\n", - HIWORD(serial), LOWORD(serial)); - else - if (media >= CDS_AUDIO) - ERR("couldn't get CD serial !\n"); -end: - CDROM_CloseDev(dev); - CDROM_Close(&wcda); - } - return serial; -} - -/************************************************************************** - * CDROM_Data_GetLabel [internal] - */ -DWORD CDROM_Data_GetLabel(WINE_CDAUDIO* wcda, char *label, int parentdev) -{ -#define LABEL_LEN 32+1 - int dev = CDROM_OPEN( wcda, parentdev ); - WORD offs = CDROM_Data_FindBestVoldesc(dev); - WCHAR label_read[LABEL_LEN]; /* Unicode possible, too */ - DWORD unicode_id = 0; - - if (offs) - { - if ((lseek(dev, offs+0x58, SEEK_SET) == offs+0x58) - && (read(dev, &unicode_id, 3) == 3)) - { - int ver = (unicode_id & 0xff0000) >> 16; - - if ((lseek(dev, offs+0x28, SEEK_SET) != offs+0x28) - || (read(dev, &label_read, LABEL_LEN) != LABEL_LEN)) - goto failure; - - CDROM_CLOSE( dev, parentdev ); - if ((LOWORD(unicode_id) == 0x2f25) /* Unicode ID */ - && ((ver == 0x40) || (ver == 0x43) || (ver == 0x45))) - { /* yippee, unicode */ - int i; - WORD ch; - for (i=0; i Intel Unicode conversion :-\ */ - ch = label_read[i]; - label_read[i] = (ch << 8) | (ch >> 8); - } - WideCharToMultiByte( CP_ACP, 0, label_read, -1, label, 12, NULL, NULL ); - label[11] = 0; - } - else - { - strncpy(label, (LPSTR)label_read, 11); - label[11] = '\0'; - } - return 1; - } - } -failure: - CDROM_CLOSE( dev, parentdev ); - ERR("error reading label !\n"); - return 0; -} - -/************************************************************************** - * CDROM_GetLabel [internal] - */ -DWORD CDROM_GetLabel(int drive, char *label) -{ - WINE_CDAUDIO wcda; - DWORD ret = 1; - - if (!(CDROM_Open(&wcda, drive))) - { - int dev = CDROM_OpenDev(&wcda); - int media = CDROM_GetMediaType(&wcda, dev); - LPSTR cdname = NULL; - - switch (media) - { - case CDS_AUDIO: - cdname = "Audio"; - strcpy(label, "Audio CD "); - break; - - case CDS_DATA_1: /* fall through for all data CD types !! */ - if (!cdname) cdname = "Data_1"; - case CDS_DATA_2: - if (!cdname) cdname = "Data_2"; - case CDS_XA_2_1: - if (!cdname) cdname = "XA 2.1"; - case CDS_XA_2_2: - if (!cdname) cdname = "XA 2.2"; - case CDS_MIXED: - if (!cdname) cdname = "Mixed mode"; - case -1: - if (!cdname) cdname = "Unknown/ISO file"; - - /* common code *here* !! */ - /* hopefully a data CD */ - if (!CDROM_Data_GetLabel(&wcda, label, dev)) - ret = 0; - break; - - case CDS_NO_INFO: - if (!cdname) cdname = "No_info"; - ret = 0; - break; - - default: - WARN("Strange CD type (%d) or empty ?\n", media); - cdname = "Strange/empty"; - ret = 0; - break; - } - - CDROM_CloseDev(dev); - CDROM_Close(&wcda); - TRACE("%s CD: label is '%s'.\n", - cdname, label); - } - else - ret = 0; - - return ret; -} - diff --git a/win32/device.c b/win32/device.c index 0856d9780a1..ce88d8f6176 100644 --- a/win32/device.c +++ b/win32/device.c @@ -319,8 +319,7 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] = -HANDLE DEVICE_Open( LPCSTR filename, DWORD access, - LPSECURITY_ATTRIBUTES sa ) +HANDLE DEVICE_Open( LPCSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ) { const struct VxDInfo *info; @@ -333,21 +332,28 @@ HANDLE DEVICE_Open( LPCSTR filename, DWORD access, return 0; } -static const struct VxDInfo *DEVICE_GetInfo( HANDLE handle ) +static DWORD DEVICE_GetClientID( HANDLE handle ) { - const struct VxDInfo *info = NULL; + DWORD ret = 0; SERVER_START_REQ( get_file_info ) { req->handle = handle; - if (!wine_server_call( req ) && - (reply->type == FILE_TYPE_UNKNOWN) && - (reply->attr & 0x10000)) - { - for (info = VxDList; info->name; info++) - if (info->id == LOWORD(reply->attr)) break; - } + if (!wine_server_call( req ) && (reply->type == FILE_TYPE_UNKNOWN)) + ret = reply->attr; } SERVER_END_REQ; + return ret; +} + +static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID ) +{ + const struct VxDInfo *info = NULL; + + if (clientID & 0x10000) + { + for (info = VxDList; info->name; info++) + if (info->id == LOWORD(clientID)) break; + } return info; } @@ -366,13 +372,13 @@ BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPDWORD lpcbBytesReturned, LPOVERLAPPED lpOverlapped) { - const struct VxDInfo *info; + DWORD clientID; TRACE( "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n", hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer, lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped ); - if (!(info = DEVICE_GetInfo( hDevice ))) + if (!(clientID = DEVICE_GetClientID( hDevice ))) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; @@ -381,7 +387,12 @@ BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, /* Check if this is a user defined control code for a VxD */ if( HIWORD( dwIoControlCode ) == 0 ) { - if ( info->deviceio ) + const struct VxDInfo *info; + if (!(info = DEVICE_GetInfo( clientID ))) + { + FIXME( "No device found for id %lx\n", clientID); + } + else if ( info->deviceio ) { return info->deviceio( dwIoControlCode, lpvInBuffer, cbInBuffer, @@ -400,7 +411,15 @@ BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, } else { - switch( dwIoControlCode ) + char str[3]; + + strcpy(str, "A:"); + str[0] += LOBYTE(clientID); + if (GetDriveTypeA(str) == DRIVE_CDROM) + return CDROM_DeviceIoControl(clientID, hDevice, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, + lpOverlapped); + else switch( dwIoControlCode ) { case FSCTL_DELETE_REPARSE_POINT: case FSCTL_DISMOUNT_VOLUME: @@ -1135,7 +1154,7 @@ static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, case VWIN32_DIOC_DOS_INT13: case VWIN32_DIOC_DOS_INT25: case VWIN32_DIOC_DOS_INT26: - case VWIN32_DIOC_DOS_DRIVEINFO: + case VWIN32_DIOC_DOS_DRIVEINFO: { CONTEXT86 cxt; DIOC_REGISTERS *pIn = (DIOC_REGISTERS *)lpvInBuffer; @@ -1160,7 +1179,7 @@ static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, case VWIN32_DIOC_DOS_INT13: INT_Int13Handler( &cxt ); break; case VWIN32_DIOC_DOS_INT25: INT_Int25Handler( &cxt ); break; case VWIN32_DIOC_DOS_INT26: INT_Int26Handler( &cxt ); break; - case VWIN32_DIOC_DOS_DRIVEINFO: DOS3Call( &cxt ); break; /* Call int 21h 730x */ + case VWIN32_DIOC_DOS_DRIVEINFO: DOS3Call( &cxt ); break; /* Call int 21h 730x */ } CONTEXT_2_DIOCRegs( &cxt, pOut );