SerialNumberの取得(2)

Vistaレジストリ情報とXPでは違っていたみたいで、このロジックでは取得できなくなってしまった。
WmiToolsを眺めていると、
Win32_PhysicalMediaに"SerialNumber"情報が入っていて、欲しい情報が取得できるみたいです。

    WmiResult disk_drive = wmi.access(_T("SELECT * FROM Win32_DiskDrive"));
    if (disk_drive.items() == 0) {
        String msg = wmi.getErrorMessage();
        return;
    }
    COUT << disk_drive.print();

    for (size_t i = 0; i < disk_drive.size(); i++) {
        String drive = WmiCall::escape(disk_drive.getString(String(_T("DeviceID")), i));
        String sub_select = WmiCall::createSelect(_T("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=\"%s\"} WHERE AssocClass = Win32_DiskDrivePhysicalMedia ResultClass = Win32_PhysicalMedia"), drive.c_str(), NULL);
        WmiResult media = wmi.access(sub_select);
        if (media.items() > 0) {
            COUT << _T("SerialNumber = ") << media.getString(_T("SerialNumber")) << endl;
        }
    }

こんな感じでVistaでも取れるようになりました。
ついでにWimCallクラスの中に、escapeと言う名前のメソッドを作成しました。

/*
 *  文字列中の'\'をエスケープするために'\\'になるように変換した文字列を返す
 *  param   : 処理の対象となる文字列(String)
 *
 *  return  : String
 */
String WmiCall::escape(String original) {
    size_t spos = 0, epos = String::npos;
    String token = String(_T(""));
    do {
        epos = original.find_first_of(_T("\\"), spos);
        if (epos != String::npos) {
            size_t count = epos - spos + 1;
            token.append(original.substr(spos, count));
            token.append(_T("\\"));
        }
        else {
            token.append(original.substr(spos));
        }
        spos = epos + 1;
    } while (epos != String::npos);
    return token;
}

これは、disk_drive.getString(String(_T("DeviceID")), i)の処理の結果として

\\.\PHYSICALDRIVE1

と言う値が帰ってくるので、これを次のWQL文に変換する時には、

\\\\.\\PHYSICALDRIVE1

のように、"\"を"\\"にエスケープするために作成しました。