I spent the past week figuring out what the actual reason for this is, and this is one of the main threads you can find on google about this issue, I thought I'd answer here. Funnily, like this thread (Fixing CD Audio with source code) I also stumbled upon this via Frogger.
Frogger had another issue, that was creating the device id with mciGetDeviceID in a different thread than it was used, but that's not relevant for the looping issue.
Since Windows Server 2k3 source code has leaked, we can easily look up what's going on under the hood (anyone who wants to work on the WINE project, stop reading here).
mcicda.dll has a function "CD_MCI_Handler" which handles the incoming messages.
This calls an internal "notify" function, which registers a "TimerProc" that runs every 100ms.
This "TimerProc" calls "CDA_drive_status", which returns a status which can be:
DISC_PLAYING, DISC_PAUSED, DISC_READY - at least are these are the ones that "TimerProc" cares about.
If the status is not "DISC_PLAYING", but is "DISC_PAUSED" or "DISC_READY" then it sends an "MCI_NOTIFY_SUCCESSFUL", which our game/program gets and then can restart the track. The issue of course is, that this never happens on Windows Vista.
So let's dig deeper. Windows XP had 3 drivers for reading CDs. cdaudio.sys (not used, gone in Win2k3), redbook.sys (used for audio playback into the xp mixer), and cdrom.sys, used for reading data discs, but also handles the playback related IOCTLs. Windows Vista only has cdrom.sys.
"CDA_drive_status" calls into "CdStatus", which sends the "IOCTL_CDROM_READ_Q_CHANNEL" with format "IOCTL_CDROM_CURRENT_POSITION" to the cdrom driver (redbook on XP). redbook on XP properly sets an "CurrentPosition.Header.AudioStatus" in a "SUB_Q_CHANNEL_DATA" struct. cdrom.sys does NOT do this.
This AudioStatus is part of the SCSI-2 spec, and is used for *audio playback* from CD drives, which of course we're not doing with our virtual drive or external drive or whatever.
https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-14.html - 14.2.10.1 Sub-Q channel data format
So redbook.sys fixed this up to pretend it's actually playing audio from a CD.
cdrom.sys doesn't fix this up, but instead passes the struct back untouched.
So now "CdStatus" never receives back anything other than "AUDIO_STATUS_NO_STATUS", because we're not actually playing audio as per SCSI-2 spec, and the whole notify logic is broken.
You can see this here: https://github.com/selfrender/Windows-Server- … da/cdio.c#L1497
So as the main post mentions, the solution would probably be keep the last and current position between 2 calls of your own TimerProc, and if it hasn't changed, your track is done and you can send the NOTIFY message yourself ... but I just wanted to know what exactly is happening here.
Vista's mcicda.dll is just a half cooked update (for Vista we have symbols from the MS symbol server), because they did change many other functions, like CdSeek, CdStop, to accomodate the IOCTLs like "IOCTL_CDROM_READ_Q_CHANNEL" being deprecated with Vista, but not CdStatus.