Hi,
I have a bit of userland code that’s been running OK for a few hundred thousand customers for the past year. Last week I had a user who has a SAN from DataPlow mounted on two Windows XP PCs, causing my code to fail. In particular, the VolumeLabelLength value of FILE_FS_VOLUME_INFORMATION returned is less than the actual length required, causing the code to go into an infinite loop.
The code that failed:
while(STATUS_BUFFER_OVERFLOW == (result = ddk.ZwQueryVolumeInformationFile(hPart.Handle, &statusBlock, volumeInformation.get(), size, informationClass)))
{
//Need to allocate more space
size = volumeInformation->VolumeLabelLength + sizeof(FILE_FS_VOLUME_INFORMATION);
volumeInformation.reset((FILE_FS_VOLUME_INFORMATION*) new unsigned char[size]);
}
TCHAR *s = p->Label.GetBuffer(volumeInformation->VolumeLabelLength/sizeof(TCHAR) + 1);
memcpy(s, volumeInformation->VolumeLabel, volumeInformation->VolumeLabelLength);
s[volumeInformation->VolumeLabelLength/sizeof(TCHAR)] = _T(‘\0’);
p->Label.ReleaseBuffer();
This would result in an infinite loop because sizeof(FILE_FS_VOLUME_INFORMATION) + the returned VolumeLabelLength after the failure is never >= the actual size required.
To work around this, I was forced to always allocate sizeof(FILE_FS_VOLUME_INFORMATION) + (MAX_PATH +1 ) * sizeof(TCHAR).
I wasn’t aware that the filesystem driver is the one to provide the value of VolumeLabelLength, and as such FILE_FS_VOLUME_INFORMATION is susceptible to returning incorrect lengths when used with buggy FS drivers…