無駄にC++の機能を使ってCDドライブ排出プログラムを書いてみた。
元々はDeviceIoControl APIの使い方を調べてたんだけど.. まぁいいか
元々はDeviceIoControl APIの使い方を調べてたんだけど.. まぁいいか
#include <windows.h>
#include <winioctl.h>
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <string>
class CdromDriveEnumerator : public std::iterator<std::input_iterator_tag, const std::string>
{
DWORD dwDrives_;
int index_;
std::string drive_;
public:
CdromDriveEnumerator()
: dwDrives_(GetLogicalDrives() << 1), index_(-1), drive_()
{++(*this);}
CdromDriveEnumerator(const CdromDriveEnumerator& x)
: dwDrives_(x.dwDrives_), index_(x.index_), drive_(x.drive_)
{}
CdromDriveEnumerator& operator =(const CdromDriveEnumerator& x)
{
dwDrives_ = x.dwDrives_;
index_ = x.index_;
drive_ = x.drive_;
return *this;
}
reference operator *() const
{
return drive_;
}
pointer operator ->() const
{
return &drive_;
}
CdromDriveEnumerator& operator ++()
{
++index_;
dwDrives_ >>= 1;
if ( dwDrives_ & 1 ) {
drive_ = std::string(1, static_cast<char>('A'+index_)).append(":");
if ( GetDriveType(drive_.c_str()) != DRIVE_CDROM ) {
++(*this);
}
}
else {
++(*this);
}
return *this;
}
CdromDriveEnumerator operator ++(int)
{
CdromDriveEnumerator ret = *this;
++(*this);
return ret;
}
private:
CdromDriveEnumerator(char drive)
: dwDrives_(0), index_(0), drive_(std::string(1, drive).append(":"))
{}
public:
static const CdromDriveEnumerator& end() {
static CdromDriveEnumerator end('Z'+1);
return end;
}
};
bool operator ==(const CdromDriveEnumerator& x, const CdromDriveEnumerator& y)
{
return *x == *y;
}
bool operator !=(const CdromDriveEnumerator& x, const CdromDriveEnumerator& y)
{
return !(x == y);
}
struct DriveEjector : public std::unary_function<const std::string&, int>
{
result_type operator()(argument_type drive) {
std::cout << "try to eject " << drive << std::endl;
HANDLE h = CreateFile(
std::string("\\\\.\\").append(drive).c_str(),
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0);
if ( h == INVALID_HANDLE_VALUE ) {
std::cerr << "failed to open volume \\\\.\\" << drive << std::endl;
return 1;
}
DWORD dwReturned;
for ( int i = 0; i < 20; ++i ) {
if ( DeviceIoControl(h, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwReturned, 0) ) {
if ( DeviceIoControl(h, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwReturned, 0) ) {
PREVENT_MEDIA_REMOVAL pmr;
pmr.PreventMediaRemoval = FALSE;
if ( DeviceIoControl(h, IOCTL_STORAGE_MEDIA_REMOVAL,
&pmr, sizeof(PREVENT_MEDIA_REMOVAL), 0, 0, &dwReturned, 0) ) {
if ( DeviceIoControl(h, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwReturned, 0) ) {
std::cout << "EJECT!" << std::endl;
}
break;
}
}
}
}
CloseHandle(h);
return 0;
}
};
int main()
{
std::for_each(CdromDriveEnumerator(), CdromDriveEnumerator::end(), DriveEjector());
return 0;
}





コメントする