-1

Problem

I'm trying to get the volume id from a physical drive.

My Code

// define disk handle
HANDLE VDHANDLE;

// set "open disk" parameters
OPEN_VIRTUAL_DISK_PARAMETERS VHD_OPEN_PARAM;
VHD_OPEN_PARAM.Version = OPEN_VIRTUAL_DISK_VERSION_1;
VHD_OPEN_PARAM.Version1.RWDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

// set storage type
VIRTUAL_STORAGE_TYPE VHD_STORAGE;
VHD_STORAGE.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
VHD_STORAGE.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

// set "attach disk" parameters
ATTACH_VIRTUAL_DISK_PARAMETERS VHD_ATTACH_PARAM;
VHD_ATTACH_PARAM.Version = ATTACH_VIRTUAL_DISK_VERSION_1;

// open disk
if ( OpenVirtualDisk( &VHD_STORAGE, L"F:\\MyStorageBunker.vhd",
                      VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG_NONE,
                      &VHD_OPEN_PARAM, &VDHANDLE ) != ERROR_SUCCESS )
{
    return ERR_MOUNT_SCRIPTCREATE;
}

// attach drive
if ( AttachVirtualDisk( VDHANDLE, 0, ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME,
                        0, &VHD_ATTACH_PARAM, 0 ) != ERROR_SUCCESS )
{
    return ERR_MOUNT_SCRIPTEXECUTE;
}

// Get attached drive & info
wchar_t DriveInfo[ MAX_PATH ];
ULONG bufferSize = sizeof( DriveInfo );
GetVirtualDiskPhysicalPath( VDHANDLE, &bufferSize, DriveInfo );
// DriveInfo raw output = \PHYSICALDISKX
// X = volume id

What I tried

std::wstringstream tmp;
int value;
char c;
std::wstringstream  ss( DriveInfo );
ss >> tmp >> c >> value;

Issue

no operator ">>" matches these operands

Questions

  1. How can I extract the volume id from wchar_t DriveInfo?
  2. Is there any way to get the volume id except GetVirtualDiskPhysicalPath?
cf-
  • 8,598
  • 9
  • 36
  • 58
TheCodingBook
  • 21
  • 1
  • 7
  • 1
    Typically, a physical drive object doesn't have a volume ID - only the individual partitions on that drive do. I *think* that would also usually be true of a mounted .vhd. (But I'm not sure about the case where you've mounted an ISO.) – Harry Johnston Jun 03 '16 at 03:56

1 Answers1

-2

I cribbed this code from somewhere I can't recall, but it seems to work for getting the serial# from the first valid drive. Sorry if it doesn't compile, I had to replace our own string class with the general one. The thing you probably want out of this is the call to GetVolumeInformation()

template <class ELT> static const ELT* NextToken(const ELT* ptr) {
    // Skip this null-terminated string
    while (*ptr != 0) {
        ptr++;
    }
    ptr++;
    return ptr;
}
int getDiskId() {
    int bufSize = GetLogicalDriveStrings(0, 0);
    WCHAR* buffer = new WCHAR[bufSize];
    GetLogicalDriveStrings(bufSize, buffer);
    std::vector<std::string> driveStrings;
    for (const WCHAR *ptr = buffer; *ptr != 0; ptr = NextToken(ptr)) {
        if (toupper(*ptr) == 'A' || toupper(*ptr) == 'B') {
            continue;
        }
        std::string tmp;
        tmp += toupper(*ptr);
        driveStrings.push_back(tmp);
    }
    // want lowest letter first
    std::sort(driveStrings.begin(), driveStrings.end());
    for (int i = 0; i < driveStrings.size(); i++) {
        DWORD dummy(0);
        DWORD serialNumber(0);
        if (
            GetVolumeInformation(
                driveStrings[i].c_str(),        // lpRootPathName
                0,          // lpVolumeNameBuffer
                0,          // nVolumeNameSize
                &serialNumber,
                &dummy,     // lpMaximumComponentLength
                &dummy,     // lpFileSystemFlags
                0,          // lpFileSystemNameBuffer
                0           // nFileSystemNameSize
            )
        ) {
            break;
        }
    }
    delete [] buffer;
    return serialNumber;
}
Wheezil
  • 3,157
  • 1
  • 23
  • 36
  • 1
    I think that's only going to work in the special case where the volume in question has a drive letter assigned. – Harry Johnston Jun 03 '16 at 03:55
  • 1
    This also does nothing to figure out *which* drive letter (if any) belongs to the drive. It's just going to pick C: 99% of the time. Also, A: and B: are legal hard drive letters. They're not reserved for anything. – nobody Jun 03 '16 at 12:06
  • @AndrewMedico: uh, technically true I suppose, but I *really* wouldn't recommend using them. I hate to think how much production code out there has similar hardcoded assumptions. – Harry Johnston Jun 04 '16 at 00:41