From 328ff6d979c028ecba9c57d12c1e75637be20396 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Sat, 8 Sep 2012 20:34:36 +0200 Subject: Add "Eject" button to main window. Since especially Windows puts the eject functionality behind an icon in the systray which is usually hidden and doesn't complain if a USB drive is unplugged without ejecting it first ejecting such a device might not be obvious to everyone. Add a button to the main window allowing to eject the selected player. Currently only implemented for Windows. Change-Id: I785ac1482cda03a1379cf6d0fd0d9a0ff8130092 --- rbutil/rbutilqt/base/utils.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++ rbutil/rbutilqt/base/utils.h | 1 + 2 files changed, 61 insertions(+) (limited to 'rbutil/rbutilqt/base') diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp index 3821b67201..cffa4b1cad 100644 --- a/rbutil/rbutilqt/base/utils.cpp +++ b/rbutil/rbutilqt/base/utils.cpp @@ -692,3 +692,63 @@ QStringList Utils::findRunningProcess(QStringList names) qDebug() << "[Utils] Found listed processes running:" << found; return found; } + + +/** Eject device from PC. + * Request the OS to eject the player. + * @param device mountpoint of the device + * @return true on success, fals otherwise. + */ +bool Utils::ejectDevice(QString device) +{ +#if defined(Q_OS_WIN32) + /* See http://support.microsoft.com/kb/165721 on the procedure to eject a + * device. */ + bool success = false; + int i; + HANDLE hdl; + DWORD bytesReturned; + TCHAR volume[8]; + + /* CreateFile */ + _stprintf(volume, _TEXT("\\\\.\\%c:"), device.toAscii().at(0)); + hdl = CreateFile(volume, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + if(hdl == INVALID_HANDLE_VALUE) + return false; + + /* lock volume to make sure no other application is accessing the volume. + * Try up to 10 times. */ + for(i = 0; i < 10; i++) { + if(DeviceIoControl(hdl, FSCTL_LOCK_VOLUME, + NULL, 0, NULL, 0, &bytesReturned, NULL)) + break; + /* short break before retry */ + Sleep(100); + } + if(i < 10) { + /* successfully locked, now dismount */ + if(DeviceIoControl(hdl, FSCTL_DISMOUNT_VOLUME, + NULL, 0, NULL, 0, &bytesReturned, NULL)) { + /* make sure media can be removed. */ + PREVENT_MEDIA_REMOVAL pmr; + pmr.PreventMediaRemoval = false; + if(DeviceIoControl(hdl, IOCTL_STORAGE_MEDIA_REMOVAL, + &pmr, sizeof(PREVENT_MEDIA_REMOVAL), + NULL, 0, &bytesReturned, NULL)) { + /* eject the media */ + if(DeviceIoControl(hdl, IOCTL_STORAGE_EJECT_MEDIA, + NULL, 0, NULL, 0, &bytesReturned, NULL)) + success = true; + } + } + } + /* close handle */ + CloseHandle(hdl); + return success; + +#endif + return false; +} + diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h index 185c0323a6..db52bfb4e9 100644 --- a/rbutil/rbutilqt/base/utils.h +++ b/rbutil/rbutilqt/base/utils.h @@ -50,6 +50,7 @@ public: static QString resolveDevicename(QString path); static QString resolveMountPoint(QString device); static QStringList findRunningProcess(QStringList names); + static bool ejectDevice(QString device); }; #endif -- cgit v1.2.3