2

I've got to read raw data from an SD card with no filesystem. This data is created by an embedded system.

My code used to work, but at some point in time it stopped working and now ReadFile() fails with error 87 (ERROR_INVALID_PARAMETER) which is not helpful at all since the parameters I'm passing seem pretty correct. I suspect that a Windows update caused this, but I'm not sure.

Here is how I open the card:

HANDLE memCard = CreateFile("\\\\.\\G:", GENERIC_READ, 
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if(memCard == INVALID_HANDLE_VALUE)
    Logger::Error("Cannot open drive G:");

On my system, the SD card is G:. The HANDLE is not INVALID_HANDLE_VALUE, so the call looks fine.

But ReadFile() fails with error 87:

unsigned long nbRead;
unsigned char sector[512];

if(!ReadFile(memCard, sector, 512, &nbRead, NULL) || nbRead != 512)
    Logger::Error("Error %u", GetLastError());

I've checked with the debugger: ReadFile() returns 0 and nbRead is 0 as well.

I've already read the "Physical Disks and Volumes" section of the CreateFile() documentation but it didn't help, it seems to me that I'm doing what's intended.

Also I'm pretty sure that the sector size is 512 bytes since that what is reported by my Linux box when I plug the card in. I've even tried the following to no avail:

bool ok = false;
unsigned long nbRead;
unsigned char sector[8192];

for(int i=1; i<=8192; ++i)
{
    if(ReadFile(memCard, sector, i, &nbRead, NULL) && nbRead == i)
    {
        ok = true;
        Logger::Error("%u worked", i);
    }
}

if(!ok)
    Logger::Error("None worked");

You guessed it, none worked. So right now I'm pretty much stucked, I've also unsuccessfully tried various CreateFile() flags such as FILE_FLAG_NO_BUFFERING.

BTW, I execute the application as the admin user (I get the initial "Do you want to allow the following program..." popup).

Any idea?

François
  • 171
  • 2
  • 10
  • Have you tried opening the drive in exclusive mode, i.e. setting the share mode to 0? – IInspectable Mar 16 '18 at 11:00
  • 1
    the read buffer size checked only in case `FO_NO_INTERMEDIATE_BUFFERING` on file - if you open it with `FILE_FLAG_NO_BUFFERING`. in this case checked also buffer (`sector` in your code) align (if device object have special `AlignmentRequirement` - you can check it by [`FILE_ALIGNMENT_INFO`](https://msdn.microsoft.com/en-us/library/windows/desktop/hh335057(v=vs.85).aspx)) or [`FILE_ALIGNMENT_INFORMATION`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_file_alignment_information) (support all win versions)). but this only in case `FILE_FLAG_NO_BUFFERING` – RbMm Mar 16 '18 at 11:15
  • this is general checks by io manager. of course concrete device can do more checks and return invalid parameter by self reasons. here question (not simply) - error from io manager (look like must not ) or device – RbMm Mar 16 '18 at 11:17
  • i be at first determinate - are error from io manager or device. for this can use event. create Manual Reset in signal state and pass it in overlapped to `ReadFile`. check event state after fail. if it in signaled state - error from io manager. if in non-signaled state - from device – RbMm Mar 16 '18 at 12:16
  • Use `VirtualAlloc` to alloc I/O buffer. `void* buffer = VirtualAlloc( 0, multiplies_of_sector_size, MEM_COMMIT, PAGE_READWRITE )` [see example](https://stackoverflow.com/a/46593940/8666197) – Daniel Sęk Mar 17 '18 at 08:55

0 Answers0