I see at least these main issues:
1) wchar_t
is the right type because you're compiling for UNICODE, you can write generic code using TCHAR
macro or explicitly declare your buffer as wchar_t
but that's what to do.
2) You have that error because you're passing wrong path to GetVolumeInformation()
(trailing backslash is required so A:
must become A:\
).
Moreover please note that you have a little bit more easy way to achieve same result, you can use GetLogicalDriveStrings()
to directly get a NULL
delimited string list. Split it using, for example, this (don't forget UNICODE) and use c_str()
with each entry.
EDIT about your modified code:
Why you drive path is A:\\
(escaped to A:\\\\
)? Just one trailing backslash is needed so mydrives
has to be declared as:
wchar_t mydrives[] = L"A:\\";
EDIT 2: there are more errors in your code so I'll post a reviewed version. There are more things I'd change but I'll point out just what doesn't actually work.
Function
retVolSno
to read volume serial number. Original version were almost right, in your modified version you perform useless character conversion. What you had to do was just to accept awchar_t
drive path.Global variable
mydrives
. You actually don't need any global variable for that. It must bewchar_t
and space before/after path are useless. One trailing backslash is needed. Line where you increment character value (++mydrives[0];
) must be changed accordingly (index 0 instead of 1).Check for drive availability. After
if(DriveMask & 1)
you did forget{
then you won't print drive name but you'll performGetVolumeInformation()
even on unavailable drives (error 123). That's why indentation is important...You're mixing UNICODE/NOT UNICODE and C/C++ stuff. I strongly suggest you pick one of them and you keep it (C or C++? UNICODE or NOT UNICODE?). For example you used C function
printf()
to print stuff and you have bothstd::string
andwchar_t
things.
Let's put everything together to have a working version. First the function to read serial number given drive path:
wstring getVolumeSerialNumber(const wchar_t* drivePath)
{
DWORD dwSerial;
wstringstream ss;
if (!GetVolumeInformation(drivePath, NULL, 0, &dwSerial, NULL, NULL, NULL, 0))
ss << L"Error: " << GetLastError();
else
ss << hex << dwSerial;
return ss.str();
}
It's almost the same as your original version, just changed to work with UNICODE characters. Then main function that cycles through available drives and print out their serial number:
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t drive[] = L"A:\\";
ULONG driveMask = _getdrives();
if (driveMask == 0)
wcout << L"_getdrives() failed with failure code: " << GetLastError() << endl;
else
{
wcout << L"This machine has the following logical drives:" << endl;
while (driveMask)
{
if (driveMask & 1)
{
wcout << drive << endl;
wcout << getVolumeSerialNumber(drive) << endl;
}
++drive[0];
driveMask >>= 1;
}
}
wcin.ignore();
return 0;
}