How to flush a storage volume’s file cache, lock and dismount it, and eject the media

來源:互聯網
上載者:User
Introduction

Ejecting a media is a well known task for CD/DVD drives. Here we get a physical ejection. But also ZIP/JAZ drives and card readers (drives with a removable media) support ejection and since they are not read only, it is required to dismount their file system
before ejection to prevent loss of data.

Background

Ejecting a media is performed by the DeviceIoControl call
IOCTL_STORAGE_EJECT_MEDIA. But it is quite reckless, it ejects even when there are open files on the drive! Therefore it's better to flush, lock, and dismount before doing it.

The Sample

This sample is a simplified version of my command-line tool EjectMedia.

It expects the drive letter to eject as a parameter. For non CD/DVD drives, the first step is to flush the file cache by means of the
FlushFileBuffers API call. It needs a handle with write access. So, for flushing a whole storage volume, we have to open it with write access, which will fail with
ERROR_ACCESS_DENIED for restricted users:

// "\\.\X:" -> to open the volumechar szVolumeAccessPath[] = "\\\\.\\X:";szVolumeAccessPath[4] = DriveLetter;HANDLE hVolWrite = CreateFile(szVolumeAccessPath,                              GENERIC_READ | GENERIC_WRITE,                              FILE_SHARE_READ | FILE_SHARE_WRITE,                              NULL, OPEN_EXISTING, 0, NULL);if ( hVolWrite != INVALID_HANDLE_VALUE ) {  FlushFileBuffers(hVolWrite);  CloseHandle(hVolWrite);}

Then we try to lock and dismount. Here read access is good enough which even restricted users can get. A lock succeeds only if there are no open handles to files on this volume. Dismount succeeds even when lock fails and there are open handles. After dismount,
all open file handles on the volume are still open but invalid, any try to use it leads to
ERROR_INVALID_HANDLE. Therefore it is an option to dismount even when the lock fails, that is the meaning of the 'Force' bool value.

bool Force = false;HANDLE hVolRead = CreateFile(szVolumeAccessPath,                  GENERIC_READ,                  FILE_SHARE_READ | FILE_SHARE_WRITE,                  NULL, OPEN_EXISTING, 0, NULL);if ( hVolRead != INVALID_HANDLE_VALUE ) {  int Locked = DeviceIoControl(hVolRead, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwRet, NULL);  if ( Locked || Force ) {    res = DeviceIoControl(hVolRead, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwRet, NULL);  }}

Finally we perform the ejection:

res = DeviceIoControl(hVolRead, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwRet, NULL);

Since we are friendly, we release the lock if we get it:

if ( Locked ) {  DeviceIoControl(hVolRead, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwRet, NULL);}

BTW: The opposite of ejection is loading a media. This really works on CD/DVD drives only:

res = DeviceIoControl(hVolRead, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &dwRet, NULL);
DiscussionWhy is there no check for drivetypes DRIVE_CDROM and DRIVE_REMOVABLE?

Windows does not care about the drive type here. The eject request is passed down to the drive's driver which passes it to the hardware. Finally it is the hardware which gives the answer. There are USB hard drives which support the eject. I've seen safe
removal failing but ejection succeeding.

What exactly is dismounting?

Dismounting means to detach the file system from the storage volume. This guarantees that the file system is not held in an inconsistent state which is important before mounting it by another driver, e.g., while the system is hibernated and you boot from
a bootable CD.

Isn't it the same as removing the drive letter (mountvol X: /D)?

No, absolutely not! The /D does not stand for dismount, it stands for deleting the mount point. And that is all it does. No flushing, no dismounting, no handles are closed or invalidated.

How do we remount a volume?

If the lock is released, then just try to open a file on the volume. Windows automatically mounts the volume then.

Why does locking take a while sometimes?

It seems that locking also flushes the file cache and this may take a little time. Furthermore, applications can register for custom notifications (RegisterDeviceNotification) and then
DBT_CUSTOMEVENT comes with GUID_IO_VOLUME_LOCK. FSCTL_LOCK_VOLUME will not return before all applications registered for custom notifications of the volume in question have processed the message.

The Demo Project

The demo project is made with VS6. It requires some headers from a Microsoft Platform SDK. No special LIBs are required.

History
  • 26 Sept 2011 - First release.
License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Uwe_Sieber

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.