A short and to-the-point C++ recipe for determining the status of your PC / laptop DVD.
To study this area in more depth, follow this link for more information, which is where I got much of this inspiration for this code snippet. It works.
http://ws0.org/windows-how-to-get-the-tray-status-of-the-optical-drive/
Full code listing
// http://ws0.org/windows-how-to-get-the-tray-status-of-the-optical-drive/ #include <Windows.h> #include <string> #include <iostream> #define SCSI_IOCTL_DATA_OUT 0 // Give data to SCSI device (e.g. for writing) #define SCSI_IOCTL_DATA_IN 1 // Get data from SCSI device (e.g. for reading) #define SCSI_IOCTL_DATA_UNSPECIFIED 2 // No data (e.g. for ejecting) #define MAX_SENSE_LEN 18 //Sense data max length #define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014 typedef unsigned short USHORT; typedef unsigned char UCHAR; typedef unsigned long ULONG; typedef void* PVOID; typedef struct _SCSI_PASS_THROUGH_DIRECT { USHORT Length; UCHAR ScsiStatus; UCHAR PathId; UCHAR TargetId; UCHAR Lun; UCHAR CdbLength; UCHAR SenseInfoLength; UCHAR DataIn; ULONG DataTransferLength; ULONG TimeOutValue; PVOID DataBuffer; ULONG SenseInfoOffset; UCHAR Cdb[16]; } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; typedef struct _SCSI_PASS_THROUGH_DIRECT_AND_SENSE_BUFFER { SCSI_PASS_THROUGH_DIRECT sptd; UCHAR SenseBuf[MAX_SENSE_LEN]; } T_SPDT_SBUF; // Get the drive letter of the first DVD device encountered std::string GetDvdDriveLetter() { std::string dvdDriveLetter = ""; DWORD drives = GetLogicalDrives(); DWORD dwSize = MAX_PATH; char szLogicalDrives[MAX_PATH] = { 0 }; DWORD dwResult = GetLogicalDriveStrings( dwSize, szLogicalDrives ); if ( dwResult > 0 && dwResult <= MAX_PATH ) { char* szSingleDrive = szLogicalDrives; while( *szSingleDrive ) { const UINT driveType = GetDriveType( szSingleDrive ); if ( driveType == 5 ) { dvdDriveLetter = szSingleDrive; dvdDriveLetter = dvdDriveLetter.substr( 0, 2 ); break; } // Get the next drive szSingleDrive += strlen(szSingleDrive) + 1; } } return dvdDriveLetter; } int GetDvdStatus() { const std::string dvdDriveLetter = GetDvdDriveLetter(); if ( dvdDriveLetter.empty() ) return -1; const std::string strDvdPath = "\\\\.\\" + dvdDriveLetter; HANDLE hDevice; // handle to the drive to be examined int iResult = -1; // results flag ULONG ulChanges = 0; DWORD dwBytesReturned; T_SPDT_SBUF sptd_sb; //SCSI Pass Through Direct variable. byte DataBuf[ 8 ]; //Buffer for holding data to/from drive. hDevice = CreateFile( strDvdPath.c_str(), // drive 0, // no access to the drive FILE_SHARE_READ, // share mode NULL, // default security attributes OPEN_EXISTING, // disposition FILE_ATTRIBUTE_READONLY, // file attributes NULL); // If we cannot access the DVD drive if (hDevice == INVALID_HANDLE_VALUE) { return -1; } // A check to see determine if a DVD has been inserted into the drive only when iResult = 1. // This will do it more quickly than by sending target commands to the SCSI iResult = DeviceIoControl((HANDLE) hDevice, // handle to device IOCTL_STORAGE_CHECK_VERIFY2, // dwIoControlCode NULL, // lpInBuffer 0, // nInBufferSize &ulChanges, // lpOutBuffer sizeof(ULONG), // nOutBufferSize &dwBytesReturned , // number of bytes returned NULL ); // OVERLAPPED structure CloseHandle( hDevice ); // Don't request the tray status as we often don't need it if( iResult == 1 ) return 2; hDevice = CreateFile( strDvdPath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if (hDevice == INVALID_HANDLE_VALUE) { return -1; } sptd_sb.sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT ); sptd_sb.sptd.PathId = 0; sptd_sb.sptd.TargetId = 0; sptd_sb.sptd.Lun = 0; sptd_sb.sptd.CdbLength = 10; sptd_sb.sptd.SenseInfoLength = MAX_SENSE_LEN; sptd_sb.sptd.DataIn = SCSI_IOCTL_DATA_IN; sptd_sb.sptd.DataTransferLength = sizeof(DataBuf); sptd_sb.sptd.TimeOutValue = 2; sptd_sb.sptd.DataBuffer = (PVOID) &( DataBuf ); sptd_sb.sptd.SenseInfoOffset = sizeof( SCSI_PASS_THROUGH_DIRECT ); sptd_sb.sptd.Cdb[ 0 ] = 0x4a; sptd_sb.sptd.Cdb[ 1 ] = 1; sptd_sb.sptd.Cdb[ 2 ] = 0; sptd_sb.sptd.Cdb[ 3 ] = 0; sptd_sb.sptd.Cdb[ 4 ] = 0x10; sptd_sb.sptd.Cdb[ 5 ] = 0; sptd_sb.sptd.Cdb[ 6 ] = 0; sptd_sb.sptd.Cdb[ 7 ] = 0; sptd_sb.sptd.Cdb[ 8 ] = 8; sptd_sb.sptd.Cdb[ 9 ] = 0; sptd_sb.sptd.Cdb[ 10 ] = 0; sptd_sb.sptd.Cdb[ 11 ] = 0; sptd_sb.sptd.Cdb[ 12 ] = 0; sptd_sb.sptd.Cdb[ 13 ] = 0; sptd_sb.sptd.Cdb[ 14 ] = 0; sptd_sb.sptd.Cdb[ 15 ] = 0; ZeroMemory(DataBuf, 8); ZeroMemory(sptd_sb.SenseBuf, MAX_SENSE_LEN); //Send the command to drive - request tray status for drive iResult = DeviceIoControl((HANDLE) hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, (PVOID)&sptd_sb, (DWORD)sizeof(sptd_sb), (PVOID)&sptd_sb, (DWORD)sizeof(sptd_sb), &dwBytesReturned, NULL); CloseHandle(hDevice); if(iResult) { if (DataBuf[5] == 0 ) iResult = 0; // DVD tray closed else if( DataBuf[5] == 1 ) iResult = 1; // DVD tray open else return iResult =2; // DVD tray closed, media present } return iResult; } int main() { // Uses the following information to obtain the status of a DVD/CD-ROM drive: // 1. GetLogicalDriveStrings() to list all logical drives // 2. GetDriveType() to obtain the type of drive // 3. DeviceIoControl() to obtain the device status // switch( GetDvdStatus() ) { case 0: std::cout << "DVD tray closed, no media" << std::endl; break; case 1: std::cout << "DVD tray open" << std::endl; break; case 2: std::cout << "DVD tray closed, media present" << std::endl; break; default: std::cout << "Drive not ready" << std::endl; break; } return 0; }
Example output: