tags:

views:

155

answers:

4

The code below is from this answer:

#include <windows.h> 

int main()
{
    HANDLE h = ::CreateFile(L"\\\\.\\d:", 0, 0, NULL, OPEN_EXISTING, 0, NULL);

    STORAGE_DEVICE_NUMBER info = {};
    DWORD bytesReturned =  0;

    ::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL);
}

When I compile and run the above,get error like this:

error C2059: syntax error : ':'
error C2059: syntax error : '}'
error C2143: syntax error : missing ';' before ':'

UPDATE

AFter saving the above as a cpp file,I got this error:

error C2664: 'CreateFileA' : cannot convert parameter 1 from 'const wchar_t [7]' to 'LPCSTR'
+9  A: 

Plain C doesn't have namespaces, so you need to leave out the :: global namespace specifiers. Those would only be valid in C++.

The L in front of the string specifies that this is a wide character string. If your project doesn't use wide characters, leave out the L to get a normal character string. If you need to support both variants you can also use the _T macro: _T("...") expands to the correct variant of string literal depending on your project settings.

sth
What does `"\\\\.\\d:"` mean here?
That's the string `\\.\d:` (backslashes in strings need to be escaped by another backslash).
sth
But what does `\\.\d:` mean?
When I try to use `_T`,get this error: `error C3861: '_T': identifier not found`
@user That's a reference to the "D:" drive in the Win32 device namespace. See http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx
Matt Gibson
@user What happens if you just skip the _T and the L and just use the string as it is? That should be perfectly compatible with the LPCSTR (long pointer to a constant string) that the function appears to be expecting, from what I recall...
Matt Gibson
Yes, it works if I skip both _T and L
@Matt Gibson ,do you know how to modify the code so that it echos something like `hd0 1` ?
You need to `#include <tchar.h>` to use `_T(...)`
Rup
+3  A: 

I'm pretty sure that you can't use :: as part of an identifier name in the C programming language. This looks more like some bizarre, bastardized usage of C++. IIRC, :: by itself in front of an identifier specified that this was in the global or file scope (to avoid potentially clashing with, say, methods in a class).

JUST MY correct OPINION
Do you know how to modify the code so that it echos something like `hd0 1` ?
+2  A: 

It's not C, it's C++. Drop the double colons (or compile it as C++).

Also, the string constant uses wide characters. Drop the L in front of the open quote.

JeremyP
or change your build to use Unicode throughout: project settings, general, character set.
Rup
A: 

Hi again!

So, I guess your question is more about getting the result you want than the reason for the code not compiling :)

Now you've got it working, the DeviceIoControl() call will be filling in the STORAGE_DEVICE_NUMBER structure you're passing to it with the results you want. So, you should find that info.DeviceType now holds the device type, info.DeviceNumber holds the device number, and info.PartitionNumber the partition number.

Test for success before using the returned values. I'd maybe try it on the C: drive rather than the D: drive, as you're doing at the moment, until I was sure it was working; at least you know you've pretty much always got a C: drive in Windows :) So, use \\\\.\\c: rather than \\\\.\\d:.

Anyway, untested, but:

if (::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL))
{
    std::cout << "Device: " << info.DeviceNumber << 
                 " Partition: " << info.PartitionNumber << std::endl;
} else {
    std::cerr << "Ooops. The DeviceIoControl call returned failure." << std::endl;
}

...obviously, you'd need a #include <iostream> for this to work, as I'm dumping the values using iostream, but you can print these out however you want, or message box them, bearing in mind you're already bringing in windows.h.

Bear in mind it's been a decade or so since I did any Windows C++ work, but maybe this'll get you going...

Matt Gibson