Development around libVLC • VLC can not read the TOC of an audio CD on Windows 11



Using VLC latest version on a Windows 11 laptop and an external USB DVD device.
VLC can not read the TOC of a regular Red Book audio CD, it presents the CD as having one long track.
When testing with Apple iTunes and Windows Media player (legacy edition), the TOC of the CD can’t be read at all.

Being a programmer myself, i have been using IOCTL_CDROM_READ_TOC / CDROM_READ_TOC_EX_FORMAT_TOC with DeviceIoControl() since Windows XP,
has always worked perfect but starting with Windows 11 the call to DeviceIoControl return TRUE but there is no info about the TOC.

If manually filling in the TOC, all other DeviceIoControl() stuff such for example IOCTL_CDROM_RAW_READ works perfect.

So the problem is with IOCTL_CDROM_READ_TOC / CDROM_READ_TOC_EX_FORMAT_TOC calls.

Seems as a bug in Windows 11?

I’m reporting the problem here on the forum, maybe there is some kind of a workaround or other ways to read the TOC of a CD?
Reporting bugs to Microsoft seems impossible.

Below is a simple code sample that illustrates the problem.

//////////////////////////////////////

Code:

#include <windows.h>#include <tchar.h>#include <stdio.h>#include <assert.h>#include <Ntddcdrm.h>BOOL IOCTL_ReadToc(HANDLE hCD, CDROM_TOC* pTOC) { DWORD dwBytesRead = 0;#if 0// works on Windows 10 but not on Windows 11 (returns false) CDROM_READ_TOC_EX TOC_EX; memset(&TOC_EX, 0, sizeof(TOC_EX)); TOC_EX.Format = CDROM_READ_TOC_EX_FORMAT_TOC; TOC_EX.Msf = 1; //Indicates the minute-second-frame bit. When set to one, this bit indicates that minute-second-frame (MSF) addressing must be used. When zero, it indicates that logical block addressing (LBA) must be used. TOC_EX.SessionTrack = 0; BOOL bRetVal = DeviceIoControl(hCD, IOCTL_CDROM_READ_TOC_EX, &TOC_EX, sizeof(TOC_EX), pTOC, sizeof(CDROM_TOC), &dwBytesRead, NULL/*&overlapped*/);#else // works on Windows 10 but not on Windows 11 (returns true but dwBytesRead == 0) BOOL bRetVal = DeviceIoControl(hCD, IOCTL_CDROM_READ_TOC, NULL, 0, pTOC, sizeof(CDROM_TOC), &dwBytesRead, NULL/*&overlapped*/);#endif printf("IOCTL_ReadToc will return %d dwBytesRead: %d\n", bRetVal, dwBytesRead); return bRetVal;}void Usage(char* sModule){TCHAR sExeName[MAX_PATH];_splitpath(sModule, NULL, NULL, sExeName, NULL);printf("Usage: %s <drive letter>\n\n", sExeName);}int _tmain(int argc, _TCHAR* argv[]){if (argc != 2) {Usage(argv[0]);return 1; } printf("Volume: %s\n", argv[1]);TCHAR sVolumeName[8];wsprintf(sVolumeName, TEXT("\\\\.\\%c:"), argv[1][0]);#define OPEN_AS_VLC_DOES 0#if OPEN_AS_VLC_DOES DWORD dwFlagsAndAttributes = FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS;#else DWORD dwFlagsAndAttributes = 0;#endifHANDLE hCD = CreateFile(sVolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); if (hCD == INVALID_HANDLE_VALUE) {fprintf(stderr, "CreateFile() Error : %d", GetLastError());return 1; } CDROM_TOC toc; memset(&toc, 0, sizeof(CDROM_TOC)); printf("sizeof(CDROM_TOC) %d\n", (int)sizeof(CDROM_TOC)); if (IOCTL_ReadToc(hCD, &toc)) { printf("Read TOC OK\n"); printf("toc.FirstTrack: %d toc.LastTrack: %d\n", toc.FirstTrack, toc.LastTrack); if (toc.FirstTrack == 1 && toc.LastTrack >= 1) { printf("CD contains one or more tracks\n"); for (int i = toc.FirstTrack - 1; i <= toc.LastTrack; i++) { printf("track %d start time: min: %d sec: %d frame: %d\n", i + 1, toc.TrackData[i].Address[1], toc.TrackData[i].Address[2], toc.TrackData[i].Address[3]); } } else { printf("IOCTL_ReadToc() returned OK but CDROM_TOC is empty!\n"); } } else { printf("Read TOC Failed!!\n"); }CloseHandle(hCD);return 0;}

Statistics: Posted by florom — 29 May 2024 13:05