?
Solved

Drive locked / Reset a cdrom drive

Posted on 2007-07-30
3
Medium Priority
?
383 Views
Last Modified: 2008-03-17
I am trying to find a way to regain control over a cdrom drive when a burning program was burning to the drive, then is terminated before completion. When the burning program is terminated, the drive is left in a state where it is locked and will not open. I have tried to unlock the drive using the code below:

DWORD dwBytesReturned;
PREVENT_MEDIA_REMOVAL PMRBuffer;

PMRBuffer.PreventMediaRemoval = fPreventRemoval;

BOOL result = DeviceIoControl( hVolume,
    IOCTL_STORAGE_MEDIA_REMOVAL,
   &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
   NULL, 0,
   &dwBytesReturned,
   NULL);

This code works if the drive has been locked normally, but does not work in my case. Does anyone know of a windows call that will effectively reset the drive? The solution should allow me to get the drive back into a known state.
0
Comment
Question by:exvagabond
  • 2
3 Comments
 

Author Comment

by:exvagabond
ID: 19593430
Here is another data point:
The drive in question is a PATA drive connected to the computer using an USB adaptor. I rebooted the attached computer and tried to open the drive with no success. After the reboot I opened the drive with a paperclip to find the disc still spinning in the drive. At any time I can try to open the drive using Explorer, and I get the following error:
D:\ is not accessible. Incorrect function.
0
 

Author Comment

by:exvagabond
ID: 19603895
For anyone interested, the problem ended up being with the state of the drive cache. The drive cache was waiting for more data. Synchronizing the drive cache solved half of the problem. This involved sending SCSI command 0x35 to the drive. The easy way to do this is to download sdparm.exe [http://sg.torque.net/sg/sdparm.html#mozTocId891504]. The difficult way is to write some windows driver code that looks like the following:

<code>
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS
{
SCSI_PASS_THROUGH spt;
ULONG Filler; // realign buffers to double word boundary
UCHAR ucSenseBuf[32];
UCHAR ucDataBuf[1024];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;

memset(&sptwb, 0,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));

sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = 0;
sptwb.spt.TargetId = 0;
sptwb.spt.Lun = 0;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = 24;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = 192;
sptwb.spt.TimeOutValue = 120;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) ;
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf );
sptwb.spt.Cdb[0] = 0xXX;
sptwb.spt.Cdb[1] = 0xXX;
sptwb.spt.Cdb[2] = 0xXX;
sptwb.spt.Cdb[3] = 0xXX;
dwLength = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength;

dwStatus = DeviceIoControl(g_hUsbDriver,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
dwLength,
&dwReturn,
FALSE);
</code>

At this point the drive will respond. However, it is locked. There are two ways to fix this. The first way is to use sdparm.exe again. The second way is to unlock the drive using Windows driver code that looks like the following:

<code>
   #include <windows.h>
   #include <winioctl.h>
   #include <tchar.h>
   #include <stdio.h>
   #include <strsafe.h>

   HANDLE OpenVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;
       UINT uDriveType;
       TCHAR szVolumeName[8];
       TCHAR szRootName[5];
       DWORD dwAccessFlags;

       wsprintf(szRootName, szRootFormat, cDriveLetter);

       uDriveType = GetDriveType(szRootName);
       switch(uDriveType) {
       case DRIVE_REMOVABLE:
           dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
           break;
       case DRIVE_CDROM:
           dwAccessFlags = GENERIC_READ;
           break;
       default:
           _tprintf(TEXT("Cannot eject.  Drive type is incorrect.\n"));
           return INVALID_HANDLE_VALUE;
       }

       wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);

       hVolume = CreateFile(   szVolumeName,
                               dwAccessFlags,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               0,
                               NULL );
       if (hVolume == INVALID_HANDLE_VALUE)
           ReportError(TEXT("CreateFile"));

       return hVolume;
   }

   BOOL CloseVolume(HANDLE hVolume)
   {
       return CloseHandle(hVolume);
   }

   #define LOCK_TIMEOUT        10000       // 10 Seconds
   #define LOCK_RETRIES        20

   BOOL LockVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;
       DWORD dwSleepAmount;
       int nTryCount;

       dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;

       // Do this in a loop until a timeout period has expired
       for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
           if (DeviceIoControl(hVolume,
                               FSCTL_LOCK_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL))
               {
                        printf("locked volume\n");
               return TRUE;
               }

           Sleep(dwSleepAmount);
       }

         printf("did not lock volume\n");
       return FALSE;
   }

   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
   {
       DWORD dwBytesReturned;
       PREVENT_MEDIA_REMOVAL PMRBuffer;

       PMRBuffer.PreventMediaRemoval = fPreventRemoval;

       BOOL result = DeviceIoControl( hVolume,
                               IOCTL_STORAGE_MEDIA_REMOVAL,
                               &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
         printf("%s prevent removal\n",result ? "did" : "did not");

         return result;
   }

   void main(int argc, char * argv[])
   {

      HANDLE cdrom = OpenVolume(argv[1][0]);

      if(cdrom == INVALID_HANDLE_VALUE)
      {
            printf("invalid handle\n");
            return;
      }      
      if(LockVolume(cdrom) == false)
      {
            printf("could not lock volume\n");
            return;
      }
      if(PreventRemovalOfVolume(cdrom, true) == false)
      {
            printf("could not prevent removal\n");
            return;
      }

      CloseVolume(cdrom);
      printf("complete\n");
       return ;
   }
</code>


In both accounts, sdparm is nicer. However, with the unlocking of the drive, I am not sure if there are any window side software locks being used in addition to the hardware lock on the drive. So, for unlocking it may be safer to do the windows call. You will need to download the Windows driver development kit in order to compile it, though.
0
 

Accepted Solution

by:
EE_AutoDeleter earned 0 total points
ID: 19768942
exvagabond,
Because you have presented a solution to your own problem which may be helpful to future searches, this question is now PAQed and your points have been refunded.

EE_AutoDeleter
0

Featured Post

Sign your company up to try the MB 660 headset now

Take control and stay focused in noisy open office environments with the MB 660. By reducing background noise, you can revitalize your office and improve concentration.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

While Plesk offers many potential benefits to website administrators, including compatibility with Windows Server and other leading technologies, the company has also been working to differentiate it from other control panels for content management…
There can be many situations demanding the conversion of Outlook OST files to PST format and as such, there is no shortage of automated tools to perform this conversion. However, what makes Stellar OST to PST converter stand above the rest? Let us e…
This tutorial will walk an individual through the process of installing the necessary services and then configuring a Windows Server 2012 system as an iSCSI target. To install the necessary roles, go to Server Manager, and select Add Roles and Featu…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question