Changed the Wine internal cdrom interface to the NT model.

oldstable
Eric Pouech 2002-01-13 01:44:00 +00:00 committed by Alexandre Julliard
parent 220c1c2c39
commit 5cc6105b39
12 changed files with 1778 additions and 1039 deletions

View File

@ -6,6 +6,7 @@ MODULE = ntdll
EXTRALIBS = $(LIBUNICODE)
C_SRCS = \
cdrom.c \
critsection.c \
debugtools.c \
exception.c \

996
dlls/ntdll/cdrom.c 100644
View File

@ -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 <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#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 <linux/cdrom.h>
#endif
#ifdef HAVE_LINUX_UCDROM_H
# include <linux/ucdrom.h>
#endif
#ifdef HAVE_SYS_CDIO_H
# include <sys/cdio.h>
#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 = &sc;
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;
}

View File

@ -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<LABEL_LEN;i++)
{ /* Motorola -> 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;

View File

@ -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 );

View File

@ -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 <stdlib.h>
#include <unistd.h>
#include "windef.h"
#include "wine/windef16.h"
#ifdef HAVE_LINUX_CDROM_H
# include <linux/cdrom.h>
#endif
#ifdef HAVE_LINUX_UCDROM_H
# include <linux/ucdrom.h>
#endif
#ifdef HAVE_SYS_CDIO_H
# include <sys/cdio.h>
#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

View File

@ -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 */

167
include/ntddcdrm.h 100644
View File

@ -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 */

229
include/ntddstor.h 100644
View File

@ -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_ */

View File

@ -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

View File

@ -7,7 +7,6 @@ VPATH = @srcdir@
MODULE = misc
C_SRCS = \
cdrom.c \
cpu.c \
error.c \
main.c \

View File

@ -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 <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#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<LABEL_LEN;i++)
{ /* Motorola -> 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;
}

View File

@ -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 );