CDROM part II

Eric Pouech eric.pouech at wanadoo.fr
Sat Jan 12 08:51:24 CST 2002


see previous message (part I)
-- 
---------------
Eric Pouech (http://perso.wanadoo.fr/eric.pouech/)
"The future will be better tomorrow", Vice President Dan Quayle
-------------- next part --------------
Name: cdrom_invk
ChangeLog: now using the NT CD interface
GenDate: 2002/01/12 14:32:23 UTC
ModifiedFiles: dlls/winmm/mcicda/mcicda.c msdos/int2f.c
AddedFiles: 
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/mcicda/mcicda.c,v
retrieving revision 1.20
diff -u -u -r1.20 mcicda.c
--- dlls/winmm/mcicda/mcicda.c	11 Jul 2001 18:56:44 -0000	1.20
+++ dlls/winmm/mcicda/mcicda.c	12 Jan 2002 08:16:42 -0000
@@ -16,11 +16,18 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "mmddk.h"
-#include "cdrom.h"
+#include "winioctl.h"
+#include "ntddstor.h"
+#include "ntddcdrm.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(mcicda);
 
+#define CDFRAMES_PERSEC                 75
+#define CDFRAMES_PERMIN                 (CDFRAMES_PERSEC * 60)
+#define FRAME_OF_ADDR(a) ((a)[1] * CDFRAMES_PERMIN + (a)[2] * CDFRAMES_PERSEC + (a)[3])
+#define FRAME_OF_TOC(toc, idx)  FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
+
 typedef struct {
     UINT		wDevID;
     int     		nUseCount;          /* Incremented for each shared open */
@@ -28,8 +35,7 @@
     WORD    		wNotifyDeviceID;    /* MCI device ID with a pending notification */
     HANDLE 		hCallback;          /* Callback handle for pending notification */
     DWORD		dwTimeFormat;
-    WINE_CDAUDIO	wcda;
-    int			mciMode;
+    HANDLE              handle;
 } WINE_MCICDAUDIO;
 
 /*-----------------------------------------------------------------------*/
@@ -80,21 +86,33 @@
 }
 
 /**************************************************************************
- * 				MCICDA_Mode			[internal]
+ * 				MCICDA_GetStatus		[internal]
  */
-static	int	MCICDA_Mode(int wcdaMode)
+static	DWORD    MCICDA_GetStatus(WINE_MCICDAUDIO* wmcda)
 {
-    switch (wcdaMode) {
-    case WINE_CDA_DONTKNOW:	return MCI_MODE_STOP;
-    case WINE_CDA_NOTREADY:	return MCI_MODE_STOP;
-    case WINE_CDA_OPEN:		return MCI_MODE_OPEN;
-    case WINE_CDA_PLAY:		return MCI_MODE_PLAY;
-    case WINE_CDA_STOP:		return MCI_MODE_STOP;
-    case WINE_CDA_PAUSE:	return MCI_MODE_PAUSE;
-    default:
-	FIXME("Unknown mode %04x\n", wcdaMode);
+    CDROM_SUB_Q_DATA_FORMAT     fmt;
+    SUB_Q_CHANNEL_DATA          data;
+    DWORD                       br;
+    DWORD                       mode = MCI_MODE_NOT_READY;
+
+    fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), 
+                         &data, sizeof(data), &br, NULL)) {
+        if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE) mode = MCI_MODE_OPEN;
+    } else {
+        switch (data.CurrentPosition.Header.AudioStatus)
+        {
+        case AUDIO_STATUS_IN_PROGRESS:          mode = MCI_MODE_PLAY;   break;
+        case AUDIO_STATUS_PAUSED:               mode = MCI_MODE_PAUSE;  break;
+        case AUDIO_STATUS_PLAY_COMPLETE:        mode = MCI_MODE_STOP;   break;
+        case AUDIO_STATUS_PLAY_ERROR:
+        case AUDIO_STATUS_NOT_SUPPORTED:
+        case AUDIO_STATUS_NO_STATUS:
+        default:
+            break;
+        }
     }
-    return MCI_MODE_STOP;
+    return mode;
 }
 
 /**************************************************************************
@@ -102,15 +120,12 @@
  */
 static	int	MCICDA_GetError(WINE_MCICDAUDIO* wmcda)
 {
-    switch (wmcda->wcda.cdaMode) {
-    case WINE_CDA_DONTKNOW:
-    case WINE_CDA_NOTREADY:	return MCIERR_DEVICE_NOT_READY;
-    case WINE_CDA_OPEN:		return MCIERR_HARDWARE;
-    case WINE_CDA_PLAY:		
-    case WINE_CDA_STOP:		
-    case WINE_CDA_PAUSE:	break;
+    switch (GetLastError())
+    {
+    case STATUS_NO_MEDIA_IN_DEVICE:     return MCIERR_DEVICE_NOT_READY;
+    case STATUS_IO_DEVICE_ERROR:        return MCIERR_HARDWARE;
     default:
-	FIXME("Unknown mode %04x\n", wmcda->wcda.cdaMode);
+	FIXME("Unknown mode %lx\n", GetLastError());
     }
     return MCIERR_DRIVER_INTERNAL;
 }
@@ -122,6 +137,9 @@
 {
     DWORD	dwFrame = 0;
     UINT	wTrack;
+    CDROM_TOC   toc;
+    DWORD       br;
+    BYTE*       addr;
     
     TRACE("(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwTime);
     
@@ -140,15 +158,20 @@
     case MCI_FORMAT_TMSF:
     default: /* unknown format ! force TMSF ! ... */
 	wTrack = MCI_TMSF_TRACK(dwTime);
-	TRACE("MSF %02u-%02u:%02u:%02u\n",
-	      MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), 
-	      MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
-	TRACE("TMSF trackpos[%u]=%lu\n",
-	      wTrack, wmcda->wcda.lpdwTrackPos[wTrack - 1]);
-	dwFrame = wmcda->wcda.lpdwTrackPos[wTrack - 1];
-	dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
-	dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
-	dwFrame += MCI_TMSF_FRAME(dwTime);
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL))
+            return 0;
+        if (wTrack < toc.FirstTrack || wTrack > toc.LastTrack)
+            return 0;
+        TRACE("MSF %02u-%02u:%02u:%02u\n",
+              MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), 
+              MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
+        addr = toc.TrackData[wTrack - toc.FirstTrack].Address;
+        TRACE("TMSF trackpos[%u]=%d:%d:%d\n",
+              wTrack, addr[0], addr[1], addr[2]);
+        dwFrame = CDFRAMES_PERMIN * (addr[0] + MCI_TMSF_MINUTE(dwTime)) +
+            CDFRAMES_PERSEC * (addr[1] + MCI_TMSF_SECOND(dwTime)) +
+            addr[2] + MCI_TMSF_FRAME(dwTime);
 	break;
     }
     return dwFrame;
@@ -157,14 +180,15 @@
 /**************************************************************************
  * 			MCICDA_CalcTime				[internal]
  */
-static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame, 
-			      LPDWORD lpRet)
+static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame, LPDWORD lpRet)
 {
     DWORD	dwTime = 0;
     UINT	wTrack;
     UINT	wMinutes;
     UINT	wSeconds;
     UINT	wFrames;
+    CDROM_TOC   toc;
+    DWORD       br;
     
     TRACE("(%p, %08lX, %lu);\n", wmcda, tf, dwFrame);
     
@@ -185,17 +209,23 @@
 	break;
     case MCI_FORMAT_TMSF:
     default:	/* unknown format ! force TMSF ! ... */
-	if (dwFrame < wmcda->wcda.dwFirstFrame || dwFrame > wmcda->wcda.dwLastFrame) {
-	    ERR("Out of range value %lu [%lu,%lu]\n", 
-		dwFrame, wmcda->wcda.dwFirstFrame, wmcda->wcda.dwLastFrame);
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL))
+            return 0;
+	if (dwFrame < FRAME_OF_TOC(toc, toc.FirstTrack) || 
+            dwFrame > FRAME_OF_TOC(toc, toc.LastTrack + 1)) {
+	    ERR("Out of range value %lu [%u,%u]\n", 
+		dwFrame, FRAME_OF_TOC(toc, toc.FirstTrack), 
+                FRAME_OF_TOC(toc, toc.LastTrack + 1));
 	    *lpRet = 0;
 	    return 0;
 	}
-	for (wTrack = 1; wTrack < wmcda->wcda.nTracks; wTrack++) {
-	    if (wmcda->wcda.lpdwTrackPos[wTrack] > dwFrame)
+	for (wTrack = toc.FirstTrack; wTrack <= toc.LastTrack; wTrack++) {
+	    if (FRAME_OF_TOC(toc, wTrack) > dwFrame)
 		break;
 	}
-	dwFrame -= wmcda->wcda.lpdwTrackPos[wTrack - 1];
+        wTrack--;
+	dwFrame -= FRAME_OF_TOC(toc, wTrack);
 	wMinutes = dwFrame / CDFRAMES_PERMIN;
 	wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
 	wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
@@ -216,9 +246,11 @@
 static DWORD MCICDA_Open(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
 {
     DWORD		dwDeviceID;
+    DWORD               ret = MCIERR_HARDWARE;
     WINE_MCICDAUDIO* 	wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
-    MCI_SEEK_PARMS 	seekParms;
-    int dev;
+    char                root[7];
+    int                 count;
+    char                drive = 0;
 
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
     
@@ -244,28 +276,54 @@
             WARN("MCI_OPEN_ELEMENT_ID %8lx ! Abort\n", (DWORD)lpOpenParms->lpstrElementName);
             return MCIERR_NO_ELEMENT_ALLOWED;
         }
-        WARN("MCI_OPEN_ELEMENT %s ignored\n",lpOpenParms->lpstrElementName);
-        /*return MCIERR_NO_ELEMENT_ALLOWED; 
-          bon 19991106 allows cdplayer.exe to run*/
+        if (!isalpha(lpOpenParms->lpstrElementName[0]) || lpOpenParms->lpstrElementName[1] != ':' ||
+            lpOpenParms->lpstrElementName[2])
+        {
+            WARN("MCI_OPEN_ELEMENT unsupported format: %s\n", lpOpenParms->lpstrElementName);
+            ret = MCIERR_NO_ELEMENT_ALLOWED; 
+            goto the_error;
+        }
+        drive = toupper(lpOpenParms->lpstrElementName[0]);
+        strcpy(root, "A:\\");
+        root[0] = drive;
+        if (GetDriveTypeA(root) != DRIVE_CDROM)
+        {
+            ret = MCIERR_INVALID_DEVICE_NAME;
+            goto the_error;
+        }
+    }
+    else
+    {
+        /* drive letter isn't passed... get the dwDeviceID'th cdrom in the system */
+        strcpy(root, "A:\\");
+        for (count = 0; root[0] <= 'Z'; root[0]++)
+        {
+            if (GetDriveTypeA(root) == DRIVE_CDROM && ++count >= dwDeviceID)
+            {
+                drive = root[0];
+                break;
+            }
+        }
+        if (!drive)
+        {
+            ret = MCIERR_INVALID_DEVICE_ID;
+            goto the_error;
+        }
     }
 
     wmcda->wNotifyDeviceID = dwDeviceID;
-    if (CDROM_Open(&wmcda->wcda, -1) == -1) {
-	--wmcda->nUseCount;
-	return MCIERR_HARDWARE;
-    }
-    wmcda->mciMode = MCI_MODE_STOP;
     wmcda->dwTimeFormat = MCI_FORMAT_MSF;
-    
-    dev = CDROM_OpenDev(&wmcda->wcda);
-    if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, dev)) {
-	wmcda->mciMode = MCI_MODE_OPEN;
-    } else {
-	MCICDA_Seek(wDevID, MCI_SEEK_TO_START, &seekParms);
-    }
-    CDROM_CloseDev(dev);
 
-    return 0;
+    /* now, open the handle */
+    strcpy(root, "\\\\.\\A:");
+    root[4] = drive;
+    wmcda->handle = CreateFileA(root, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    if (wmcda->handle != INVALID_HANDLE_VALUE)
+        return 0;
+
+ the_error:
+    --wmcda->nUseCount;
+    return ret;
 }
 
 /**************************************************************************
@@ -279,10 +337,9 @@
 
     if (wmcda == NULL) 	return MCIERR_INVALID_DEVICE_ID;
     
-    if (wmcda->nUseCount == 1) {
-	CDROM_Close(&wmcda->wcda);
+    if (--wmcda->nUseCount == 0) {
+	CloseHandle(wmcda->handle);
     }
-    wmcda->nUseCount--;
     return 0;
 }
 
@@ -350,6 +407,36 @@
     return ret;
 }
 
+static DWORD CDROM_Audio_GetSerial(CDROM_TOC* toc)
+{
+    unsigned long serial = 0;
+    int i;
+    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 = toc->TrackData[0].Address[3];
+    dwStart = FRAME_OF_TOC(*toc, toc->FirstTrack);
+
+    for (i = 0; i <= toc->LastTrack - toc->FirstTrack; i++) {
+        serial += (toc->TrackData[i].Address[1] << 16) | 
+            (toc->TrackData[i].Address[2] << 8) | toc->TrackData[i].Address[3];
+    }
+    dwEnd = FRAME_OF_TOC(*toc, toc->LastTrack + 1);
+ 
+    if (toc->LastTrack - toc->FirstTrack + 1 < 3)
+        serial += wMagic + (dwEnd - dwStart);
+
+    return serial;
+}
+    
+
 /**************************************************************************
  * 				MCICDA_Info			[internal]
  */
@@ -373,23 +460,16 @@
     } else if (dwFlags & MCI_INFO_MEDIA_UPC) {
 	ret = MCIERR_NO_IDENTITY;
     } else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
-	DWORD	res = 0;
-	int dev = CDROM_OpenDev(&wmcda->wcda);
+	DWORD	    res = 0;
+        CDROM_TOC   toc;
+        DWORD       br;
 
-	if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, dev)) {
-	    CDROM_CloseDev(dev);
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL)) {
 	    return MCICDA_GetError(wmcda);
 	}
-	CDROM_CloseDev(dev);
 
-	res = CDROM_Audio_GetSerial(&wmcda->wcda);
-	if (wmcda->wcda.nTracks <= 2) {
-	    /* there are some other values added when # of tracks < 3
-	     * for most Audio CD it will do without
- 	     */
-	    FIXME("Value is not correct !! "
-                  "Please report with full audio CD information (-debugmsg +cdrom,mcicda)\n");
-	}
+	res = CDROM_Audio_GetSerial(&toc);
 	sprintf(buffer, "%lu", res);
 	str = buffer;
     } else {
@@ -415,8 +495,13 @@
  */
 static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
 {
-    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    DWORD	        ret = 0;
+    WINE_MCICDAUDIO*	        wmcda = MCICDA_GetOpenDrv(wDevID);
+    DWORD                       idx;
+    DWORD	                ret = 0;
+    CDROM_SUB_Q_DATA_FORMAT     fmt;
+    SUB_Q_CHANNEL_DATA          data;
+    CDROM_TOC                   toc;
+    DWORD                       br;
 
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
@@ -432,33 +517,38 @@
 	TRACE("dwItem = %lx\n", lpParms->dwItem);
 	switch (lpParms->dwItem) {
 	case MCI_STATUS_CURRENT_TRACK:
-	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, -1)) {
+            fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+            if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), 
+                                 &data, sizeof(data), &br, NULL))
+            {
 		return MCICDA_GetError(wmcda);
 	    }
-	    lpParms->dwReturn = wmcda->wcda.nCurTrack;
+	    lpParms->dwReturn = data.CurrentPosition.TrackNumber;
 	    TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_LENGTH:
-	    if (wmcda->wcda.nTracks == 0) {
-		if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, -1)) {
-		    WARN("error reading TracksInfo !\n");
-		    return MCICDA_GetError(wmcda);
-		}
+            if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                                 &toc, sizeof(toc), &br, NULL)) {
+                WARN("error reading TOC !\n");
+                return MCICDA_GetError(wmcda);
 	    }
 	    if (dwFlags & MCI_TRACK) {
 		TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
-		if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
+		if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
 		    return MCIERR_OUTOFRANGE;
-		lpParms->dwReturn = wmcda->wcda.lpdwTrackLen[lpParms->dwTrack - 1];
+                idx = lpParms->dwTrack - toc.FirstTrack;
+		lpParms->dwReturn = FRAME_OF_TOC(toc, lpParms->dwTrack + 1) - 
+                    FRAME_OF_TOC(toc, lpParms->dwTrack);
 		/* Windows returns one frame less than the total track length for the
 		   last track on the CD.  See CDDB HOWTO.  Verified on Win95OSR2. */
-		if (lpParms->dwTrack == wmcda->wcda.nTracks)
+		if (lpParms->dwTrack == toc.LastTrack)
 		    lpParms->dwReturn--;
 	    } else {
 		/* Sum of the lengths of all of the tracks.  Inherits the
 		   'off by one frame' behavior from the length of the last track.
 		   See above comment. */
-		lpParms->dwReturn = wmcda->wcda.dwLastFrame - wmcda->wcda.dwFirstFrame - 1;
+		lpParms->dwReturn = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
+                    FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
 	    }
 	    lpParms->dwReturn = MCICDA_CalcTime(wmcda, 
 						 (wmcda->dwTimeFormat == MCI_FORMAT_TMSF) 
@@ -468,51 +558,70 @@
 	    TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_MODE:
-	    CDROM_Audio_GetCDStatus(&wmcda->wcda, -1);
-	    lpParms->dwReturn = MCICDA_Mode(wmcda->wcda.cdaMode);
-	    if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
+            lpParms->dwReturn = MCICDA_GetStatus(wmcda);
 	    TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
 	    lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
 	    ret = MCI_RESOURCE_RETURNED;
 	    break;
 	case MCI_STATUS_MEDIA_PRESENT:
-	    CDROM_Audio_GetCDStatus(&wmcda->wcda, -1);
-	    lpParms->dwReturn = (wmcda->wcda.nTracks == 0 || 
-				 wmcda->wcda.cdaMode == WINE_CDA_OPEN) ?
+	    lpParms->dwReturn = (MCICDA_GetStatus(wmcda) == MCI_MODE_OPEN) ?
 		MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
 	    TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
 	    ret = MCI_RESOURCE_RETURNED;
 	    break;
 	case MCI_STATUS_NUMBER_OF_TRACKS:
-	    lpParms->dwReturn = CDROM_Audio_GetNumberOfTracks(&wmcda->wcda, -1);
+            if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                                 &toc, sizeof(toc), &br, NULL)) {
+                WARN("error reading TOC !\n");
+                return MCICDA_GetError(wmcda);
+	    }
+	    lpParms->dwReturn = toc.LastTrack - toc.FirstTrack + 1;
 	    TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
 	    if (lpParms->dwReturn == (WORD)-1) 
 		return MCICDA_GetError(wmcda);
 	    break;
 	case MCI_STATUS_POSITION:
-	    if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, -1)) 
-		return MCICDA_GetError(wmcda);
-	    if(wmcda->wcda.cdaMode == WINE_CDA_OPEN)
-		return MCIERR_HARDWARE;
-	    lpParms->dwReturn = wmcda->wcda.dwCurFrame;
 	    if (dwFlags & MCI_STATUS_START) {
-		lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
+                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                                     &toc, sizeof(toc), &br, NULL)) {
+                    WARN("error reading TOC !\n");
+                    return MCICDA_GetError(wmcda);
+                }
+		lpParms->dwReturn = FRAME_OF_TOC(toc, toc.FirstTrack);
 		TRACE("get MCI_STATUS_START !\n");
-	    }
-	    if (dwFlags & MCI_TRACK) {
-		if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
+	    } else if (dwFlags & MCI_TRACK) {
+                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                                     &toc, sizeof(toc), &br, NULL)) {
+                    WARN("error reading TOC !\n");
+                    return MCICDA_GetError(wmcda);
+                }
+		if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
 		    return MCIERR_OUTOFRANGE;
-		lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
+		lpParms->dwReturn = FRAME_OF_TOC(toc, lpParms->dwTrack);
 		TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
-	    }
+            } else {
+                fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), 
+                                     &data, sizeof(data), &br, NULL)) {
+                    return MCICDA_GetError(wmcda);
+                }
+                lpParms->dwReturn = FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
+            }
 	    lpParms->dwReturn = MCICDA_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
 	    TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
 	    break;
 	case MCI_STATUS_READY:
 	    TRACE("MCI_STATUS_READY !\n");
-	    lpParms->dwReturn = (wmcda->wcda.cdaMode == WINE_CDA_DONTKNOW ||
-				 wmcda->wcda.cdaMode == WINE_CDA_NOTREADY) ?
-		MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
+            switch (MCICDA_GetStatus(wmcda))
+            {
+            case MCI_MODE_NOT_READY:
+            case MCI_MODE_OPEN:
+                lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
+                break;
+            default:
+                lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
+                break;
+            }
 	    TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms->dwReturn));
 	    ret = MCI_RESOURCE_RETURNED;
 	    break;
@@ -526,15 +635,16 @@
 	    if (!(dwFlags & MCI_TRACK)) 
 		ret = MCIERR_MISSING_PARAMETER;
 	    else {
-		if(!CDROM_Audio_GetTracksInfo(&wmcda->wcda, -1)) {
-		    WARN("Error reading tracks info\n");
-		    return MCICDA_GetError(wmcda);
-		}
-		if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
+                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                                     &toc, sizeof(toc), &br, NULL)) {
+                    WARN("error reading TOC !\n");
+                    return MCICDA_GetError(wmcda);
+                }
+		if (lpParms->dwTrack < toc.FirstTrack || lpParms->dwTrack > toc.LastTrack)
 		    ret = MCIERR_OUTOFRANGE;
 		else
-		    lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
-				     CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
+		    lpParms->dwReturn = (toc.TrackData[lpParms->dwTrack - toc.FirstTrack].Control & 0x04) ?
+                                         MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
 	    }
 	    TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
 	    break;
@@ -553,11 +663,14 @@
  */
 static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
 {
-    int 		start, end;
-    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    DWORD		ret = 0;
-    int dev = -1;
-    
+    WINE_MCICDAUDIO*	        wmcda = MCICDA_GetOpenDrv(wDevID);
+    DWORD		        ret = 0, start, end;
+    CDROM_TOC                   toc;
+    DWORD                       br;
+    CDROM_PLAY_AUDIO_MSF        play;
+    CDROM_SUB_Q_DATA_FORMAT     fmt;
+    SUB_Q_CHANNEL_DATA          data;
+ 
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (lpParms == NULL)
@@ -566,48 +679,45 @@
     if (wmcda == NULL)
 	return MCIERR_INVALID_DEVICE_ID;
 
-    dev = CDROM_OpenDev(&wmcda->wcda);
-    if (wmcda->wcda.nTracks == 0) {
-	if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda, dev)) {
-	    WARN("error reading TracksInfo !\n");
-	    ret = MCIERR_DRIVER_INTERNAL;
-	    goto end;
-	}
-    }
-    wmcda->wcda.nCurTrack = 1;
     if (dwFlags & MCI_FROM) {
 	start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom);
-	TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
+	TRACE("MCI_FROM=%08lX -> %lu \n", lpParms->dwFrom, start);
     } else {
-	if (!CDROM_Audio_GetCDStatus(&wmcda->wcda, dev))
-	{
-	    ret = MCIERR_DRIVER_INTERNAL;
-	    goto end;
-	}
-	start = wmcda->wcda.dwCurFrame;
+        fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), 
+                             &data, sizeof(data), &br, NULL)) {
+            return MCICDA_GetError(wmcda);
+        }
+        start = FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
     }
     if (dwFlags & MCI_TO) {
 	end = MCICDA_CalcFrame(wmcda, lpParms->dwTo);
-	TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
-    } else
-	end = wmcda->wcda.dwLastFrame;
-
-    if (CDROM_Audio_Play(&wmcda->wcda, start, end, dev) == -1)
-    {
-	ret = MCIERR_HARDWARE;
-	goto end;
+	TRACE("MCI_TO=%08lX -> %lu \n", lpParms->dwTo, end);
+    } else {
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL)) {
+            WARN("error reading TOC !\n");
+            return MCICDA_GetError(wmcda);
+        }
+	end = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1;
     }
-    wmcda->mciMode = MCI_MODE_PLAY;
-    if (dwFlags & MCI_NOTIFY) {
+    TRACE("Playing from %lu to %lu\n", start, end);
+    play.StartingM = start / CDFRAMES_PERMIN;
+    play.StartingS = (start / CDFRAMES_PERSEC) % 60;
+    play.StartingF = start % CDFRAMES_PERSEC;
+    play.EndingM   = end / CDFRAMES_PERMIN;
+    play.EndingS   = (end / CDFRAMES_PERSEC) % 60;
+    play.EndingF   = end % CDFRAMES_PERSEC;
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play), 
+                         NULL, 0, &br, NULL)) {
+	ret = MCIERR_HARDWARE;
+    } else if (dwFlags & MCI_NOTIFY) {
 	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 	/*
 	  mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
 	  wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
 	*/
     }
-end:
-    if (dev != -1)
-        CDROM_CloseDev(dev);
     return ret;
 }
 
@@ -617,15 +727,15 @@
 static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
     WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    
+    DWORD               br;
+
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDROM_Audio_Stop(&wmcda->wcda, -1) == -1)
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL))
 	return MCIERR_HARDWARE;
 
-    wmcda->mciMode = MCI_MODE_STOP;
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
 	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 	mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
@@ -640,14 +750,15 @@
 static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
     WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    
+    DWORD               br;
+
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDROM_Audio_Pause(&wmcda->wcda, 1, -1) == -1)
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL))
 	return MCIERR_HARDWARE;
-    wmcda->mciMode = MCI_MODE_PAUSE;
+
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 	mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
@@ -662,14 +773,15 @@
 static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
 {
     WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
+    DWORD               br;
     
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDROM_Audio_Pause(&wmcda->wcda, 0, -1) == -1)
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_RESUME_AUDIO, NULL, 0, NULL, 0, &br, NULL))
 	return MCIERR_HARDWARE;
-    wmcda->mciMode = MCI_MODE_STOP;
+
     if (lpParms && (dwFlags & MCI_NOTIFY)) {
 	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 	mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
@@ -683,23 +795,35 @@
  */
 static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
 {
-    DWORD		at;
-    WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    
+    DWORD		        at;
+    WINE_MCICDAUDIO*	        wmcda = MCICDA_GetOpenDrv(wDevID);
+    CDROM_SEEK_AUDIO_MSF        seek;
+    CDROM_TOC                   toc;
+    DWORD                       br;
+
     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
     
     if (wmcda == NULL)	return MCIERR_INVALID_DEVICE_ID;
     if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
     
-    wmcda->mciMode = MCI_MODE_SEEK;
     switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
     case MCI_SEEK_TO_START:
 	TRACE("Seeking to start\n");
-	at = wmcda->wcda.dwFirstFrame;
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL)) {
+            WARN("error reading TOC !\n");
+            return MCICDA_GetError(wmcda);
+        }
+        at = FRAME_OF_TOC(toc, toc.FirstTrack);
 	break;
     case MCI_SEEK_TO_END:
 	TRACE("Seeking to end\n");
-	at = wmcda->wcda.dwLastFrame;
+        if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, 
+                             &toc, sizeof(toc), &br, NULL)) {
+            WARN("error reading TOC !\n");
+            return MCICDA_GetError(wmcda);
+        }
+	at = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1;
 	break;
     case MCI_TO:
 	TRACE("Seeking to %lu\n", lpParms->dwTo);
@@ -710,9 +834,13 @@
 	      (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)));
 	return MCIERR_UNSUPPORTED_FUNCTION;
     }
-    if (CDROM_Audio_Seek(&wmcda->wcda, at, -1) == -1) {
+    seek.M = at / CDFRAMES_PERMIN;
+    seek.S = (at / CDFRAMES_PERSEC) % 60;
+    seek.F = at % CDFRAMES_PERSEC;
+    if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek), 
+                         NULL, 0, &br, NULL))
 	return MCIERR_HARDWARE;
-    }
+
     if (dwFlags & MCI_NOTIFY) {
 	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
 	mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
@@ -724,17 +852,20 @@
 /**************************************************************************
  * 				MCICDA_SetDoor			[internal]
  */
-static DWORD	MCICDA_SetDoor(UINT wDevID, int open)
+static DWORD	MCICDA_SetDoor(UINT wDevID, BOOL open)
 {
     WINE_MCICDAUDIO*	wmcda = MCICDA_GetOpenDrv(wDevID);
-    
+    DWORD               br;
+
     TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
     
     if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
     
-    if (CDROM_SetDoor(&wmcda->wcda, open, -1) == -1)
+    if (!DeviceIoControl(wmcda->handle, 
+                         (open) ? IOCTL_STORAGE_EJECT_MEDIA : IOCTL_STORAGE_LOAD_MEDIA,
+                         NULL, 0, NULL, 0, &br, NULL))
 	return MCIERR_HARDWARE;
-    wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
+      
     return 0;
 }
 
Index: msdos/int2f.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/msdos/int2f.c,v
retrieving revision 1.38
diff -u -u -r1.38 int2f.c
--- msdos/int2f.c	4 Dec 2001 19:54:49 -0000	1.38
+++ msdos/int2f.c	12 Jan 2002 13:46:22 -0000
@@ -4,7 +4,7 @@
  *
  *  Cdrom - device driver emulation - Audio features.
  * 	(c) 1998 Petr Tomasek <tomasek at etf.cuni.cz>
- *	(c) 1999 Eric Pouech
+ *	(c) 1999,2002 Eric Pouech
  */
 
 #include "config.h"
@@ -15,7 +15,9 @@
 #include "module.h"
 /* #define DEBUG_INT */
 #include "debugtools.h"
-#include "cdrom.h"
+#include "winioctl.h"
+#include "ntddstor.h"
+#include "ntddcdrm.h"
 
 DEFAULT_DEBUG_CHANNEL(int);
 
@@ -414,12 +416,19 @@
 #define MSCDEX_Dump(pfx, req, drm)
 #endif
 
+#define CDFRAMES_PERSEC                 75
+#define CDFRAMES_PERMIN                 (CDFRAMES_PERSEC * 60) 
+#define FRAME_OF_ADDR(a)        ((a)[1] * CDFRAMES_PERMIN + (a)[2] * CDFRAMES_PERSEC + (a)[3])
+#define FRAME_OF_TOC(toc, idx)  FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
+#define CTRL_OF_TOC(toc, idx)   (((toc).TrackData[idx - (toc).FirstTrack].Control << 4) | \
+                                  (toc).TrackData[idx - (toc).FirstTrack].Adr)
+
 static	void	MSCDEX_StoreMSF(DWORD frame, BYTE* val)
 {
     val[3] = 0;	/* zero */
     val[2] = frame / CDFRAMES_PERMIN; /* minutes */
-    val[1] = (frame - CDFRAMES_PERMIN * val[2]) / CDFRAMES_PERSEC; /* seconds */
-    val[0] = frame - CDFRAMES_PERMIN * val[2] - CDFRAMES_PERSEC * val[1]; /* frames */
+    val[1] = (frame / CDFRAMES_PERSEC) % 60; /* seconds */
+    val[0] = frame % CDFRAMES_PERSEC; /* frames */
 }
 
 static int is_cdrom( int drive)
@@ -434,7 +443,7 @@
     int 	drive, count;
     char*	p;
 
-    switch(LOBYTE(context->Eax)) {
+    switch (LOBYTE(context->Eax)) {
     case 0x00: /* Installation check */
 	/* Count the number of contiguous CDROM drives
 	 */
@@ -470,13 +479,18 @@
 	
     case 0x10: /* direct driver access */
 	{
-	    static 	WINE_CDAUDIO	wcda;
-	    int		dev = -1;
 	    BYTE* 	driver_request;
 	    BYTE* 	io_stru;	
 	    BYTE 	Error = 255; /* No Error */ 
 	    int		dorealmode = ISV86(context);
-	    
+            char        devName[] = "\\\\.\\@:";
+	    HANDLE      h;
+            CDROM_TOC                   toc;
+            CDROM_SUB_Q_DATA_FORMAT     fmt;
+            SUB_Q_CHANNEL_DATA          data;
+            DWORD                       br;
+            DWORD                       present = TRUE;
+
 	    driver_request = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx);
 	    
 	    if (!driver_request) {
@@ -489,16 +503,13 @@
 		return;
 	    }
 	    /* FIXME
-	     *       - the current implementation only supports a single CD ROM
+             * the following tests are wrong because lots of functions don't require the
+             * tray to be closed with a CD inside
 	     */
-	    CDROM_Open(&wcda, -1);
-	    dev = CDROM_OpenDev(&wcda);
 	    TRACE("CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]);
 	    
-	    for (drive = 0; drive < 26; drive++) if (is_cdrom(drive)) break;
-	    /* drive contains the first CD ROM */
-	    if (CX_reg(context) != drive) {
-		WARN("Request made doesn't match a CD ROM drive (%d/%d)\n", CX_reg(context), drive);
+	    if (!is_cdrom(CX_reg(context))) {
+		WARN("Request made doesn't match a CD ROM drive (%d)\n", CX_reg(context));
 		driver_request[4] |= 0x80;
 		driver_request[3] = 1;	/* unknown unit */
 		return;
@@ -508,8 +519,39 @@
 	    
 	    /* set status to 0 */
 	    PTR_AT(driver_request, 3, WORD) = 0;
-	    CDROM_Audio_GetCDStatus(&wcda, dev);
-	    
+            devName[4] = 'A' + CX_reg(context);
+            h = CreateFileA(devName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+            if (!h) {
+		WARN("Couldn't open cdrom handle\n");
+		driver_request[4] |= 0x80;
+		driver_request[3] = 1;	/* unknown unit */
+		return;
+	    }
+
+            fmt.Format = IOCTL_CDROM_CURRENT_POSITION;
+            if (!DeviceIoControl(h, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL) ||
+                !DeviceIoControl(h, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), 
+                                 &data, sizeof(data), &br, NULL)) {
+                if (GetLastError() == STATUS_NO_MEDIA_IN_DEVICE)
+                {
+                    if (driver_request[2] != 6 && driver_request[2] != 15)
+                    {
+                        driver_request[4] |= 0x80;
+                        driver_request[3] = 2;	/* drive not ready */
+                        CloseHandle(h);
+                        return;
+                    }
+                    present = FALSE;
+                }
+                else
+                {
+                    driver_request[4] |= 0x80;
+                    driver_request[3] = 1;	/* unknown unit */
+                    CloseHandle(h);
+                    return;
+                }
+            }
+               
 	    switch (driver_request[2]) {
 	    case 3:
 		io_stru = (dorealmode) ? 
@@ -548,10 +590,12 @@
 		case 1: /* location of head */
 		    switch (io_stru[1]) {
 		    case 0:
-			PTR_AT(io_stru, 2, DWORD) = wcda.dwCurFrame;
+			PTR_AT(io_stru, 2, DWORD) = 
+                            FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress);
 			break;
 		    case 1:
-			MSCDEX_StoreMSF(wcda.dwCurFrame, io_stru + 2);
+			MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), 
+                                        io_stru + 2);
 			break;
 		    default:
 			ERR("CD-ROM driver: unsupported addressing mode !!\n");
@@ -588,13 +632,13 @@
 		     * 0	Door locked
 		     * 0	see below (Door closed/opened)
 		     */
-		    if (wcda.cdaMode == WINE_CDA_OPEN)
-			io_stru[1] |= 1;
+		    if (!present) PTR_AT(io_stru, 1, DWORD) |= 1;
 		    TRACE(" ----> DEVICE STATUS <0x%08lx>\n", PTR_AT(io_stru, 1, DWORD));
 		    break;
 		    
 		case 8: /* Volume size */
-		    PTR_AT(io_stru, 1, DWORD) = wcda.dwLastFrame;
+		    PTR_AT(io_stru, 1, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1) -
+                        FRAME_OF_TOC(toc, toc.FirstTrack) - 1;
 		    TRACE(" ----> VOLUME SIZE <%ld>\n", PTR_AT(io_stru, 1, DWORD));
 		    break;
 		    
@@ -605,20 +649,20 @@
 		    break;
 		    
 		case 10: /* audio disk info */
-		    io_stru[1] = wcda.nFirstTrack; /* starting track of the disc */
-		    io_stru[2] = wcda.nLastTrack;  /* ending track */
-		    MSCDEX_StoreMSF(wcda.dwLastFrame, io_stru + 3);
+		    io_stru[1] = toc.FirstTrack; /* starting track of the disc */
+		    io_stru[2] = toc.LastTrack;  /* ending track */
+		    MSCDEX_StoreMSF(FRAME_OF_TOC(toc, toc.LastTrack + 1) -
+                                    FRAME_OF_TOC(toc, toc.FirstTrack) - 1, io_stru + 3);
 		    
 		    TRACE(" ----> AUDIO DISK INFO <%d-%d/%08lx>\n",
 			  io_stru[1], io_stru[2], PTR_AT(io_stru, 3, DWORD));
 		    break;
 		    
 		case 11: /* audio track info */
-		    if (io_stru[1] >= wcda.nFirstTrack && io_stru[1] <= wcda.nLastTrack) {
-			int	 nt = io_stru[1] - wcda.nFirstTrack;
-			MSCDEX_StoreMSF(wcda.lpdwTrackPos[nt], io_stru + 2);
+		    if (io_stru[1] >= toc.FirstTrack && io_stru[1] <= toc.LastTrack) {
+			MSCDEX_StoreMSF(FRAME_OF_TOC(toc, io_stru[1]), io_stru + 2);
 			/* starting point if the track */
-			io_stru[6] = (wcda.lpbTrackFlags[nt] & 0xF0) >> 4;
+			io_stru[6] = CTRL_OF_TOC(toc, io_stru[1]);
 		    } else {
 			PTR_AT(io_stru, 2, DWORD) = 0;
 			io_stru[6] = 0;
@@ -628,42 +672,43 @@
 		    break;
 		    
 		case 12: /* get Q-Channel info */
-		    io_stru[1] = wcda.lpbTrackFlags[wcda.nCurTrack - 1];
-		    io_stru[2] = wcda.nCurTrack;
+		    io_stru[1] = CTRL_OF_TOC(toc, data.CurrentPosition.TrackNumber);
+		    io_stru[2] = data.CurrentPosition.TrackNumber;
 		    io_stru[3] = 0; /* FIXME ?? */ 
 
 		    /* why the heck did MS use another format for 0MSF information... sigh */
 		    {
 			BYTE	bTmp[4];
 
-			MSCDEX_StoreMSF(wcda.dwCurFrame - wcda.lpdwTrackPos[wcda.nCurTrack - 1], bTmp);
+			MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.TrackRelativeAddress), bTmp);
 			io_stru[ 4] = bTmp[2];
 			io_stru[ 5] = bTmp[1];
 			io_stru[ 6] = bTmp[0];
 			io_stru[ 7] = 0;
 
-			MSCDEX_StoreMSF(wcda.dwCurFrame, bTmp);
+			MSCDEX_StoreMSF(FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), bTmp);
 			io_stru[ 8] = bTmp[2];
 			io_stru[ 9] = bTmp[1];
 			io_stru[10] = bTmp[0];
 			io_stru[11] = 0;
 		    }		    
-		    TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08lx, tp=%08lx)\n",
+		    TRACE("Q-Channel info: Ctrl/adr=%02x TNO=%02x X=%02x rtt=%02x:%02x:%02x rtd=%02x:%02x:%02x (cf=%08x, tp=%08x)\n",
 			  io_stru[ 1], io_stru[ 2], io_stru[ 3], 
 			  io_stru[ 4], io_stru[ 5], io_stru[ 6], 
 			  io_stru[ 8], io_stru[ 9], io_stru[10],
-			  wcda.dwCurFrame, wcda.lpdwTrackPos[wcda.nCurTrack - 1]);
+			  FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress), 
+                          FRAME_OF_TOC(toc, data.CurrentPosition.TrackNumber));
 		    break;
 		    
 		case 15: /* Audio status info */
 		    /* !!!! FIXME FIXME FIXME !! */
-		    PTR_AT(io_stru, 1,  WORD) = 2 | ((wcda.cdaMode == WINE_CDA_PAUSE) ? 1 : 0);
-		    if (wcda.cdaMode == WINE_CDA_OPEN) {
+		    PTR_AT(io_stru, 1,  WORD) = 2 | ((data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED) ? 1 : 0);
+		    if (!present) {
 			PTR_AT(io_stru, 3, DWORD) = 0;
 			PTR_AT(io_stru, 7, DWORD) = 0;
 		    } else {
-			PTR_AT(io_stru, 3, DWORD) = wcda.lpdwTrackPos[0];
-			PTR_AT(io_stru, 7, DWORD) = wcda.lpdwTrackPos[wcda.nTracks - 1];
+			PTR_AT(io_stru, 3, DWORD) = FRAME_OF_TOC(toc, toc.FirstTrack);
+			PTR_AT(io_stru, 7, DWORD) = FRAME_OF_TOC(toc, toc.LastTrack + 1);
 		    }
 		    TRACE("Audio status info: status=%04x startLoc=%ld endLoc=%ld\n",
 			  PTR_AT(io_stru, 1, WORD), PTR_AT(io_stru, 3, DWORD), PTR_AT(io_stru, 7, DWORD));
@@ -684,18 +729,18 @@
 		TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]); 
 		switch (io_stru[0]) {
 		case 0: /* eject */ 
-		    CDROM_SetDoor(&wcda, 1, dev);
+                    DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &br, NULL);
 		    TRACE(" ----> EJECT\n"); 
 		    break;
 		case 2: /* reset drive */
-		    CDROM_Reset(&wcda, dev);
+		    DeviceIoControl(h, IOCTL_STORAGE_RESET_DEVICE, NULL, 0, NULL, 0, &br, NULL);
 		    TRACE(" ----> RESET\n"); 
 		    break;
 		case 3: /* Audio Channel Control */
 		    FIXME(" ----> AUDIO CHANNEL CONTROL (NIY)\n");
 		    break;
 		case 5: /* close tray */
-		    CDROM_SetDoor(&wcda, 0, dev);
+                    DeviceIoControl(h, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &br, NULL);
 		    TRACE(" ----> CLOSE TRAY\n"); 
 		    break;
 		default:
@@ -705,10 +750,57 @@
 		}	
 		break;
 		
+            case 128: /* read long */
+                {
+                    LPVOID              dst = MapSL(MAKESEGPTR(PTR_AT(driver_request, 16, WORD), 
+                                                               PTR_AT(driver_request, 14, WORD)));
+                    DWORD               at = PTR_AT(driver_request, 20, DWORD);
+                    WORD                num = PTR_AT(driver_request, 18, WORD);
+                    RAW_READ_INFO       rri;
+
+		    switch (driver_request[13]) {
+		    case 1: /* Red book addressing mode = 0:m:s:f */
+			/* FIXME : frame <=> msf conversion routines could be shared
+			 * between mscdex and mcicda
+			 */
+			at = LOBYTE(HIWORD(at)) * CDFRAMES_PERMIN +
+			    HIBYTE(LOWORD(at)) * CDFRAMES_PERSEC +
+			    LOBYTE(LOWORD(at));
+			/* fall through */
+		    case 0: /* HSG addressing mode */
+                        switch (PTR_AT(driver_request, 24, BYTE))
+                        {
+                        case 0: /* cooked */
+                            ReadFile(h, dst, num * 2048, &br, NULL);
+                            break;
+                        case 1:
+                            /* FIXME: computation is wrong */
+                            rri.DiskOffset.s.HighPart = 0;
+                            rri.DiskOffset.s.LowPart = at << 11;
+                            rri.TrackMode = YellowMode2;
+                            rri.SectorCount = num;
+                            DeviceIoControl(h, IOCTL_CDROM_RAW_READ, &rri, sizeof(rri), 
+                                            dst, num * 2352, &br, NULL);
+			break;
+                        default:
+                            ERR("Unsupported read mode !!\n");
+                            Error = 0x0c;
+                            break;
+                        }
+                        break;
+		    default:
+			ERR("Unsupported address mode !!\n");
+			Error = 0x0c;
+			break;
+		    }
+                }
+                break;
+
 	    case 131: /* seek */
 		{
-		    DWORD	at;
-		    
+		    DWORD	                at;
+                    CDROM_SEEK_AUDIO_MSF        seek;
+
 		    at = PTR_AT(driver_request, 20, DWORD);
 		    
 		    TRACE(" --> SEEK AUDIO mode :<0x%02X>, [%ld]\n", 
@@ -724,7 +816,11 @@
 			    LOBYTE(LOWORD(at));
 			/* fall through */
 		    case 0: /* HSG addressing mode */
-			CDROM_Audio_Seek(&wcda, at, dev);
+                        seek.M = at / CDFRAMES_PERMIN;
+                        seek.S = (at / CDFRAMES_PERSEC) % 60;
+                        seek.F = at % CDFRAMES_PERSEC;
+                        DeviceIoControl(h, IOCTL_CDROM_SEEK_AUDIO_MSF, &seek, sizeof(seek), 
+                                        NULL, 0, &br, NULL);
 			break;
 		    default:
 			ERR("Unsupported address mode !!\n");
@@ -736,8 +832,9 @@
 
 	    case 132: /* play */
 		{
-		    DWORD	beg, end;
-		    
+		    DWORD	                beg, end;
+                    CDROM_PLAY_AUDIO_MSF        play;
+
 		    beg = end = PTR_AT(driver_request, 14, DWORD);
 		    end += PTR_AT(driver_request, 18, DWORD);
 		    
@@ -745,19 +842,27 @@
 			  (BYTE)driver_request[13], beg, end);
 		    
 		    switch (driver_request[13]) {
-		    case 1: /* Red book addressing mode = 0:m:s:f */
+		    case 1: 
+			/* Red book addressing mode = 0:m:s:f */
 			/* FIXME : frame <=> msf conversion routines could be shared
 			 * between mscdex and mcicda
 			 */
-			beg = LOBYTE(HIWORD(beg)) * CDFRAMES_PERMIN +
+			beg = LOBYTE(LOWORD(beg)) * CDFRAMES_PERMIN +
 			    HIBYTE(LOWORD(beg)) * CDFRAMES_PERSEC +
-			    LOBYTE(LOWORD(beg));
-			end = LOBYTE(HIWORD(end)) * CDFRAMES_PERMIN +
+			    LOBYTE(HIWORD(beg));
+			end = LOBYTE(LOWORD(end)) * CDFRAMES_PERMIN +
 			    HIBYTE(LOWORD(end)) * CDFRAMES_PERSEC +
-			    LOBYTE(LOWORD(end));
+			    LOBYTE(HIWORD(end));
 			/* fall through */
 		    case 0: /* HSG addressing mode */
-			CDROM_Audio_Play(&wcda, beg, end, dev);
+                        play.StartingM = beg / CDFRAMES_PERMIN;
+                        play.StartingS = (beg / CDFRAMES_PERSEC) % 60;
+                        play.StartingF = beg % CDFRAMES_PERSEC;
+                        play.EndingM   = end / CDFRAMES_PERMIN;
+                        play.EndingS   = (end / CDFRAMES_PERSEC) % 60;
+                        play.EndingF   = end % CDFRAMES_PERSEC;
+                        DeviceIoControl(h, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play), 
+                                        NULL, 0, &br, NULL);
 			break;
 		    default:
 			ERR("Unsupported address mode !!\n");
@@ -768,18 +873,18 @@
 		break;
 		
 	    case 133:
-		if (wcda.cdaMode == WINE_CDA_PLAY) {
-		    CDROM_Audio_Pause(&wcda, 1, dev);
+		if (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
+                    DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
 		    TRACE(" --> STOP AUDIO (Paused)\n");
 		} else {
-		    CDROM_Audio_Stop(&wcda, dev);
+                    DeviceIoControl(h, IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &br, NULL);
 		    TRACE(" --> STOP AUDIO (Stopped)\n");
 		}
 		break;
 		
 	    case 136:
 		TRACE(" --> RESUME AUDIO\n");
-		CDROM_Audio_Pause(&wcda, 0, dev);
+                DeviceIoControl(h, IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &br, NULL);
 		break;
 		
 	    default:
@@ -792,14 +897,14 @@
 		driver_request[4] |= 0x80;
 		driver_request[3] = Error;
 	    }
-	    
-	    CDROM_CloseDev(dev);
-	    CDROM_Close(&wcda);
+
+	    CloseHandle(h);
 	    /* setting status bits
 	     * 3 == playing && done
 	     * 1 == done 
 	     */
-	    driver_request[4] |= (wcda.cdaMode == WINE_CDA_PLAY) ? 3 : 1;
+	    driver_request[4] |= 
+                (data.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) ? 3 : 1;
 	    
 	    MSCDEX_Dump("End", driver_request, dorealmode);
 	}


More information about the wine-patches mailing list