Need Help with DeviceIoControl function

May 4, 2016 at 5:40pm
This is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
HANDLE HandelUsb= CreateFile(L"\\\\.\\G:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (HandelUsb == INVALID_HANDLE_VALUE)
    {
        printf("Terminal failure: Unable to open usb ERROR CODE:0x%x\n", GetLastError());
        return 1;
    }
 
    DISK_GEOMETRY d = { 0 };
    DWORD dwReturned = 0;
   
    int gs =DeviceIoControl(HandelUsb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &d, sizeof(DISK_GEOMETRY),&dwReturned, NULL);
    printf("%d\n", gs);
   
    if (d.MediaType == RemovableMedia)
    {
        DWORD dwReturned2 = 0;
        MEDIA_SERIAL_NUMBER_DATA data={ 0 };
        if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
                printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
        }
        else {
                printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());
           
        }
    }
 
    CloseHandle(HandelUsb);
    return 0;


Everything works well except for the function

DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)

It always fails (returns a value of 0), GetLastError returns the value 0X1 (problem function).

Maybe someone here can show me what I'm missing here?

* I ran Windus 7
Last edited on May 4, 2016 at 5:41pm
May 4, 2016 at 7:01pm
Diagnostically, what would happen if you opened the file handle with 'GENERIC_ALL' access? Also, try the 'FILE_ATTRIBUTE_NORMAL' attribute flag (second from the end).
May 4, 2016 at 7:30pm
'GENERIC_ALL' access - caused the error 0X5 in function CreateFile.
'FILE_ATTRIBUTE_NORMAL' -> Did not make any change in DeviceIoControl function results.
May 4, 2016 at 8:32pm
Try adding 'GENERIC_EXECUTE' to the access rights then. That error code means that one of the operations you are trying to perform is not valid with the supplied handle, the most common cause of that is access rights.
May 4, 2016 at 9:01pm
I added, GENERIC EXECUTE, there is no error in CreateFile
But there is no change DeviceIoControl (still continues to get there 0X1)
May 5, 2016 at 1:43pm
The other explanation is that the drivers for that device don't support this control code. Try some other control codes and if most of the other ones work then we can chalk this up to a device driver issue.
May 5, 2016 at 2:15pm
I tried 7 different USB devices, the world got the same result...
May 5, 2016 at 2:28pm
And are they all using the same driver? What does Device Manager tell you?
May 5, 2016 at 3:11pm
I just checked two of them , they use in different Drivers
Last edited on May 5, 2016 at 3:11pm
May 5, 2016 at 3:28pm
I wonder if you're connecting to the wrong device for this information? What happens if you use the DeviceId instead of the drive letter? 'Control Panel' -> 'Administrative Tools' -> 'Computer Management' then in the Console Tree on the left side you may have to expand the Storage container to see Disk Management, but the DeviceId will be there, sort of. For example, if you want the name Id of 'Disk 1', that will be '\\PhysicalDrive1', you need to add the appropriate escape characters.

There is some logic to this, the SerialNumber property is a member of Win32_DiskDrive class where as the drive letter would be Win32_LogicalDisk. The later has a member called VolumeSerialNumber but that isn't the same thing.
Last edited on May 5, 2016 at 3:34pm
May 5, 2016 at 3:37pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    //volume handle to device handle
VOLUME_DISK_EXTENTS volumeToDevice = { 0 };
DWORD Returned = 0;
DeviceIoControl(HandelToUsb,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL,0,&volumeToDevice,sizeof(VOLUME_DISK_EXTENTS),&Returned,NULL);


WCHAR volume[150] ;
swprintf_s(volume, L"\\\\.\\PhysicalDrive%d", volumeToDevice.Extents[0].DiskNumber);
wprintf(L"%s\n", volume);

//handle to phisicalDrive
HANDLE HandelUsb = CreateFile(volume, 0, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
DWORD dwReturned2 = 0;
    MEDIA_SERIAL_NUMBER_DATA data={ 0 };
    if (DeviceIoControl(HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, &data,sizeof(MEDIA_SERIAL_NUMBER_DATA), &dwReturned2, NULL)) {
            printf("SerialNumberLength %d\nResult %d\nReserved[2] %s\nSerialNumberData[1] %s ", data.SerialNumberLength, data.Result, data.Reserved, data.SerialNumberData);
    }
    else {
            printf("faild to get serial number ERROR CODE:0x%x\n", GetLastError());

    }

I tried this code (uses a phisical Drive), and still got the same error, 0X1

The odd thing to me is a special function:
1
2
DeviceIoControl (HandelUsb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, & d, sizeof (DISK_GEOMETRY), & dwReturned, NULL);
DeviceIoControl(HandelToUsb,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,NULL,0,&volumeToDevice,sizeof(VOLUME_DISK_EXTENTS),&Returned,NULL);

Are without error and only function:
DeviceIoControl (HandelUsb, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, NULL, 0, & data, sizeof (MEDIA_SERIAL_NUMBER_DATA), & dwReturned2, NULL)
Return 0x1 error ...
May 5, 2016 at 3:58pm
Which is why I suspected the driver. DeviceIoControl only mediates between you and the device driver, if that driver it is talking to doesn't support the function you are trying to call then Incorrect Function is exactly the error code I would expect to see. Try typing this into a command line, you may have to elevate the permissions:
 
wmic diskdrive get name, serialnumber

This should list the all of the drives you have on your system by their DeviceID and their respective serial numbers, this will at least tell us if the device you are targeting has one. If it does, which I assume it does, then we are back to this being a permissions issue of some sort. Have you tried running your compiled executable from an elevated command prompt?
May 5, 2016 at 4:39pm
I tried it on the command line, it works well and gave the serial number of the USB (and hard disk)
I tried to run my software with administrator privileges, yet I get the error 0X1
May 5, 2016 at 5:11pm
Then we're looking at something weird. I assume that you created the 'MEDIA_SERIAL_NUMBER_DATA' struct exactly like the documentation says? I would expect it to crash or return with Invalid parameter if you hadn't but I'm reaching here. Can you post all of your code?
May 5, 2016 at 6:59pm
I created the 'MEDIA_SERIAL_NUMBER_DATA' struct exactly like the documentation.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363419%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
May 5, 2016 at 7:21pm
In that case I'd have to test this out myself. I'm not someplace that I have a dev env setup right now.
Topic archived. No new replies allowed.