読者です 読者をやめる 読者になる 読者になる

Natural Software

KinectなどのDepthセンサーを中心に活動しています

デバイス情報の取得

プログラム C++ Win32

はてな記法シンタックス・ハイライトというのが楽しいのでソースをはっつけてみる。
※使用は自己責任で。


とりあえずデバイス情報の取得を。
DDKのヘッダがないと定義が通らない箇所がある。自分で定義するには量が多いので、すなおにDDKのヘッダを使用したほうが良さそう。

最初に注意点をMSDNのCreateFileの解説から抜粋

ロッピーディスク x や、ハードディスクのパーティション x を開くには、lpFileName パラメータで\\.\x: と指定します。例を示します。
文字列 意味
\\.\A: ユーザーのコンピュータのドライブ A のハンドルを取得します。
\\.\C: ユーザーのコンピュータのドライブ C のハンドルを取得します。
ドライブ名の後に円記号(\)を付けないでください。文字列 "\\\\.\\C:\\" を指定すると、ドライブ C のルートディレクトリを意味します。


・dwCreationDistribution パラメータで、OPEN_EXISTING を指定しなければなりません。
フロッピーディスクや、ハードディスクのパーティションを開く場合、dwShareMode パラメータで
FILE_SHARE_WRITE フラグを指定しなければなりません。


おソース
2008/02/17 printfをstd::coutに変更

// <devioctl.h>と<winioctl.h>内で定義が被るため<winioctl.h>は
// インクルードしないようにする
#define _WINIOCTL_

#include <windows.h>
#include <iostream>
#include <string>
#include <iomanip>

// DDKのヘッダファイル
#include <devioctl.h>
#include <ntdddisk.h> 

// caseの値をそのまま文字列で返す
#define CASE_RETURN( val )  case val: return #val; break

// デバイス種別
enum DeviceType
{
    DriveTypeUnknown   = DRIVE_UNKNOWN,     // ドライブの種類を判別できませんでした。
    DriveTypeNoRootDir = DRIVE_NO_ROOT_DIR, // 指定のルートディレクトリが存在しません。
                                            // たとえば、パスにボリュームがマウントされていません
                                            // (未フォーマットや、メディアが挿入されていないなど)。
    DriveTypeRemovable = DRIVE_REMOVABLE,   // このディスクは、ドライブから取り出せます。
    DriveTypeFixed     = DRIVE_FIXED,       // このディスクは、ドライブから取り出せません。
    DriveTypeRemote    = DRIVE_REMOTE,      // このドライブは、リモート(ネットワーク)ドライブです。
    DriveTypeCdrom     = DRIVE_CDROM,       // このドライブは、CD-ROM ドライブです。
    DriveTypeRamdisk   = DRIVE_RAMDISK,     // このドライブは、RAM ディスクです。
};

// デバイス種別を文字列で返す
const char* getDeviceTypeName( UINT deviceType )
{
    switch ( deviceType ){
    CASE_RETURN( DriveTypeNoRootDir );
    CASE_RETURN( DriveTypeRemovable );
    CASE_RETURN( DriveTypeFixed );
    CASE_RETURN( DriveTypeRemote );
    CASE_RETURN( DriveTypeCdrom );
    CASE_RETURN( DriveTypeRamdisk );
    }

    return "DriveTypeUnknown";
}

// バス種別を文字列で取得
const char* getBusTypeName( STORAGE_BUS_TYPE type )
{
    switch ( type ){
    CASE_RETURN( BusTypeScsi );
    CASE_RETURN( BusTypeAtapi );
    CASE_RETURN( BusTypeAta );
    CASE_RETURN( BusType1394 );
    CASE_RETURN( BusTypeSsa );
    CASE_RETURN( BusTypeFibre );
    CASE_RETURN( BusTypeUsb );
    CASE_RETURN( BusTypeRAID );
    CASE_RETURN( BusTypeMaxReserved );
    }

    return "BusTypeUnknown";
}

void main()
{
    BOOL ret;

    // 論理デバイスを取得
    DWORD logicDevice = ::GetLogicalDrives();
    for ( int i = 0; i <= ('Z' - 'A'); ++i ) {
        // ドライブが設定されていなければ何もしない
        if ( ((logicDevice >> i) & 1) == 0 ) {
            continue;
        }

        char drive = 'A' + i;

        // デバイス種別を取得
        char volume[] = "A:\\";
        volume[0] = drive;

        UINT deviceType = ::GetDriveType( volume );
        std::cout << volume << std::endl;
        std::cout << ::getDeviceTypeName( deviceType ) << std::endl;

        // ドライブのハンドルを取得
        char device[] = { "\\\\.\\A:" };
        device[4] =  drive;

        HANDLE hDevice = ::CreateFile( device, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
                                        0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
        if ( hDevice != INVALID_HANDLE_VALUE ) {
            // ドライブ情報を取得
            DWORD dwRet;
            unsigned char buffer[1024] = { 0 };
            STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*)buffer;
            STORAGE_PROPERTY_QUERY sPQ = { StorageDeviceProperty,  PropertyStandardQuery };

            ret = ::DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &sPQ, sizeof(sPQ),
                                        sdd, sizeof(buffer), &dwRet, 0 );
            if ( ret ) {
                std::cout << "Version               : " << sdd->Version << std::endl;
                std::cout << "Size                  : " << sdd->Size << std::endl;
                std::cout << "DeviceType            : " << (int)sdd->DeviceType << std::endl;
                std::cout << "DeviceTypeModifier    : " << (int)sdd->DeviceTypeModifier << std::endl;
                std::cout << "RemovableMedia        : " << (int)sdd->RemovableMedia << std::endl;
                std::cout << "CommandQueueing       : " << (int)sdd->CommandQueueing << std::endl;
                std::cout << "VendorIdOffset        : " << sdd->VendorIdOffset << std::endl;
                std::cout << "ProductIdOffset       : " << sdd->ProductIdOffset << std::endl;
                std::cout << "ProductRevisionOffset : " << sdd->ProductRevisionOffset << std::endl;
                std::cout << "SerialNumberOffset    : " << sdd->SerialNumberOffset << std::endl;
                std::cout << "BusType               : " << ::getBusTypeName( sdd->BusType ) << std::endl;
                std::cout << "RawPropertiesLength   : " << sdd->RawPropertiesLength << std::endl;

                // オフセットはRawDevicePropertiesの先頭アドレスからではなく
                // バッファの先頭からのオフセット
                std::cout << "VendorId              : " << &buffer[sdd->VendorIdOffset] << std::endl;
                std::cout << "ProductId             : " << &buffer[sdd->ProductIdOffset] << std::endl;
                std::cout << "ProductRevision       : " << &buffer[sdd->ProductRevisionOffset] << std::endl;
                if ( (sdd->SerialNumberOffset != 0) && (sdd->SerialNumberOffset != -1) ) {
                    std::cout << "SerialNumber          : " << &buffer[sdd->SerialNumberOffset] << std::endl;
                }
            }

            std::cout << std::endl;

            // ハンドルを閉じる
            ::CloseHandle( hDevice );
        }
    }
}
// EOF