Click here to Skip to main content
Email Password   helpLost your password?

Screenshot - CDorDV1.jpg

Introduction

The code included with this article demonstrates a way to determine whether an installed drive is a CD or DVD drive. The return from GetDriveType() only tells you that the drive is a DRIVE_CDROM, and it returns this for both CD and DVD (so far as I could tell). The additional code included here will help you determine the difference between a CD and DVD drive.

Background

I needed to know this information for a project a while back, but I couldn't find anything that encapsulated it using MFC. So, I wrote this small program to test out some ideas and ended up with the code included with this article.

Using the code

There is nothing fancy in this code. Users can simply cut and paste the code needed from this sample into their own projects.

Here is the part that does the work in question:

//

CDORDVD CCDOrDVDDriveDlg::GetMediaType(TCHAR cDrive)
{
    CString cs;
    cs.Format(_T("\\\\.\\%c:"),cDrive);
    HANDLE hDrive = CreateFile(cs, GENERIC_READ, FILE_SHARE_READ, 
                               NULL, OPEN_EXISTING, 0, NULL);

    if(hDrive == INVALID_HANDLE_VALUE || GetLastError() != NO_ERROR)
        return CDDRIVE_UNKNOWN;

    UCHAR buffer[2048]; // Must be big enough hold DEVICE_MEDIA_INFO

    ULONG returned;
    BOOL bStatus = DeviceIoControl(hDrive, 
                   IOCTL_STORAGE_GET_MEDIA_TYPES_EX,NULL, 0, 
                   &buffer, 2048, &returned, NULL);

    // Close handle. This should work, but if it can't close it something may

    // have gone wrong in the IOCTL call.

    if (!bStatus || !CloseHandle(hDrive))
        return CDDRIVE_UNKNOWN;

    PGET_MEDIA_TYPES pMediaTypes = (PGET_MEDIA_TYPES) buffer;
    if(pMediaTypes->DeviceType == FILE_DEVICE_CD_ROM)
        return CDDRIVE_CD;
    else if(pMediaTypes->DeviceType == FILE_DEVICE_DVD)
        return CDDRIVE_DVD;

    return CDDRIVE_UNKNOWN;
}

Points of interest

I tried several ideas while creating this small snippet of code. I needed it to work on any version of Windows from WinNT. I needed to know the difference because the user of my program can have either kind of media and I wanted to display the most logical drive for them to use.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Questionwhat about a CD-RW or DVD -RW Drive
Vis_liner
7:36 22 May '07  
how a program to detect if a CD-RW or DVD-RW installed on a machine hardware ?Smile
GeneralPossible handle leak?
Blake Miller
7:40 2 Apr '07  
if (!bStatus || !CloseHandle(hDrive))
return CDDRIVE_UNKNOWN;


If this undergoes early evaluation and bStatus is false, you will not close the file handle and will result in a file handle leak in your application.

Probably should change order.

if( !CloseHandle(hDrive) || !bStatus )
return CDDRIVE_UNKNOWN;


To make sure that file handle gets closed.

Also, why would you not evaluate the buffer just because you could not close the file handle?
If bStatus is true, doesn't that mean you actually obtained valid results?

GeneralRe: Possible handle leak?
tserface
9:24 2 Apr '07  
Thanks Blake. You're right. I'll fix that today. I never thought about it not being able to close the handle and yet something still be right in the buffer. I guess that's a possibility. To be honest, I've never had the call fail so I guess I don't know if that would work or not. I may have been a little too paranoid. Of course, you would think that if I receieved valid results I would always be able to close the handle so perhaps it's moot.

Thanks for the tip on the handle thing. That statement used to be an && and I changed it a while back to make the code more concise.

Tom
GeneralRe: Possible handle leak?
Nathan Lewis
6:31 11 Jun '07  
As long as we're on the subject, this is potentially problematic as well:

if(hDrive == INVALID_HANDLE_VALUE || GetLastError() != NO_ERROR)
return CDDRIVE_UNKNOWN;

According to the CreateFile API documentation, GetLastError() will only return a valid error code under two circumstances:

    1. If you set dwCreationDisposition to CREATE_ALWAYS or OPEN_ALWAYS, GetLastError() will return ERROR_ALREADY_EXISTS if the file exists, otherwise it returns zero. This obviously doesn't apply in this case, though, as you're using OPEN_EXISTING.

    2. If the function fails, GetLastError() will return "extended error information".

Nowhere does the documentation say that GetLastError() will return NO_ERROR - or anything else, for that matter - upon a successful call to CreateFile. The fact that it does appear to do so notwithstanding, it's never a good idea to count on undocumented behaviors, IMHO.

On the other hand, the documentation does clearly state that "[i]f the function succeeds, the return value is an open handle to a specified file." So if hDrive != INVALID_HANDLE_VALUE, we can safely assume the function succeeded.

So let's assume for the moment that CreateFile has succeeded, and yet GetLastError() returns an error code of some kind - in this case, you will return without closing the handle. It would be much better to simply do this:

if( hDrive == INVALID_HANDLE_VALUE )
return CDDRIVE_UNKNOWN;

But, of course, I am most likely just being extremeley paranoid here - I am going by a very strict interpretation of the current version of the API documentation. Chances are this problem will never occur in actual practice. But I always figure it's better to be paranoid than to potentially introduce a bug that would be very difficult to track down.... Poke tongue

IMO, YMMV, etc.



*Real* programmers use "copy con:progname.exe"!

QuestionBlueray and HDDVD drives ?
IntVestor
7:35 29 Mar '07  
CDs and DVDs are all right. But soon they'll be obsolete. I suggest to expand this function to new drive types. If you want of course. Anyway, thank you for contribution to the community.
AnswerRe: Blueray and HDDVD drives ?
tserface
7:40 29 Mar '07  
I doubt that CD's or DVD's will ever go away, but your point is well taken. I'll try to add code for some of the newer similar drives.
GeneralTranslation to another language
Anthony Slash
13:07 27 Mar '07  
It's posible you can translate this code to another language (like C# or VB.NET)...???

Cause i don't understand the code what you published...

I hope you can help me with this...
GeneralRe: Translation to another language
tserface
13:19 27 Mar '07  
Here is a link to a similar (albeit more complicated) article for someting similar for VB. Maybe this will help get you started. The calling parameters would be the same:

http://vbnet.mvps.org/index.html?code/disk/getmediatype.htm[^]

I didn't try this, I just found it using Google to see if I could find something to help you.

Tom
GeneralRe: Translation to another language
tserface
13:36 27 Mar '07  
Oops, that link didn't work. Try this or just cut and paste it into your browser:

http://vbnet.mvps.org/index.html?code/disk/getmediatype.htm

Tom
GeneralRe: Translation to another language
Anthony Slash
16:50 27 Mar '07  
That code was made with VB 6.0...

And i need some code made with C# or VB.NET...

Thanks any way...
GeneralRe: Translation to another language
Balboos
5:36 5 Apr '07  
It might be prudent (even wise) for you to become read-familiar with unmanaged C++.

It's not that I am without simpathy, as I was always cursing under by breath when the only code examples were given in VB: I never learned Basic (Fortran -> Vax Assembler-> C-> C++. . .).

One reason I've 'bought in' to .NET is that, finally, the same calls are useable in all languages*. VB.NET snippets are now pretty much readable.

You're familar, it would seem, with C#. C++ isn't so different, although it does keep you in touch with what you're actually doing (at the price of some extra typing). Think of it as a visit to your ancestoral home.

Balboos

*(occasionally requiring 15 .Missing arguments, and no documentation, but what the hell, right?)

"The difference between genius and stupidity is that genius has its limits." - Albert Einstein


Last Updated 27 Mar 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010