1

I have been working on a fantasy console type project. I decided to zero a flash drive I had laying around and use it as the ROM input to the fantasy console. While trying to write code to read bytes directly from the drive (rather than from a file on the drive) I have found a peculiar bug.

Trying to open the drive via CreateFile and ReadFile with the file path \\.\\PhysicalDrive1 results in the error ""\\.\\PhysicalDrive1" is not a core dump: file format not recognized"

I have tried changing input options and I have tried alternate file paths, but anything I try results in the drive either not being found or the error shown above. Information on this issue is very scarse from my research, and what little info I have found is specific to Linux, and involves very different situations.

Here is my code (not the cleanest but it should work):

#include <windows.h>
#include <fileapi.h>
#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
    printf("Opening %s\n", argv[1]);

    HANDLE romf = CreateFile((LPCSTR)argv[1], 
                                GENERIC_READ,
                                FILE_SHARE_READ, 
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);
    
    if (romf == INVALID_HANDLE_VALUE) {
        printf("File %s not found\n", argv[1]);
        return -1;
    }

    uint8_t rom[4] = { 0 };
    LPDWORD read = 0;

    int res = ReadFile(romf, rom, 4, read, NULL);
    if (res == 0) {
        printf("Error reading file (%d)\n", argv[1], GetLastError());
        
        CloseHandle(romf);
        return -1;
    }
    
    printf("Read $%x bytes\n", read);

    printf("%02x %02x %02x %02x\n", rom[0], rom[1], rom[2], rom[3]);

    CloseHandle(romf);

    return 0;
}

I have used gdb to debug the code and to get the error message.

Tobi Noara
  • 19
  • 3
  • `\\.\\PhysicalDrive1` in any case is is wrong. need use `\\\\?\\PhysicalDrive1` if you want open `PhysicalDrive1` – RbMm Jun 05 '22 at 06:56
  • `(LPCSTR)argv[1]` is a bug. If you need to cast, you're doing it wrong. Either call `CreateFileA`, or - preferably - use `CreateFileW` and supply a wide character string. The easiest way is to define a [`wmain`](https://learn.microsoft.com/en-us/cpp/c-language/using-wmain) entry point. If you cannot do that you can call [`CommandLineToArgvW`](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw) passing the return value of [`GetCommandLineW`](https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinew). – IInspectable Jun 05 '22 at 07:43

1 Answers1

1

Nothing in the code you have shown produces the error message that you have claimed. That error message is a debugger message, not a compiler error, or a runtime system error. This issue has nothing to do with the code you have shown, and everything to do with how you are using the debugger.

Per the gdb documentation:

You can also start with both an executable program and a core file specified:

gdb program core

In comments, you state that you are running gdb ./bin/clt \\.\\PhysicalDrive1, which means you are calling gdb with \\.\\PhysicalDrive1 in the core parameter, but that path does not point to a valid core dump file, hence the error. You are expecting gdb to pass \\.\\PhysicalDrive1 as a command-line parameter to your program, but that is not what it is actually doing. To do that, use the --args parameter (see How do I run a program with commandline arguments using GDB within a Bash script?), eg:

gdb --args ./bin/clt \\.\PhysicalDrive1


That said, there are a number of bugs in your code.

  • you are not checking if argc > 1 is true before accessing argv[1].

  • the LPCSTR cast in the lpFileName parameter of CreateFile() is not needed and should be removed. argv[1] is a char* and you are casting it to const char* (which CreateFile() wants, if you are compiling a MBCS build and not a UNICODE build). The compiler can do that cast implicitly for you.

  • you are passing a NULL pointer to the lpNumberOfBytesRead parameter of ReadFile(). Per the documentation:

    [out, optional] lpNumberOfBytesRead

    A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.

    This parameter can be NULL only when the lpOverlapped parameter is not NULL.

    You are not performing an asynchronous read, so you must provide a pointer to an actual DWORD variable instead:

    DWORD read = 0;
    
    int res = ReadFile(romf, rom, 4, &read, NULL);
    
  • your error message when ReadFile() fails is being formatted incorrectly. You forgot to include a %s placeholder for argv[1], so you are passing argv[1] (a char*) to the %d placeholder, which expects an int, and you are not passing the value of GetLastError() to any placeholder at all. You need to fix your format string, eg:

    printf("Error reading file %s (%d)\n", argv[1], GetLastError());
    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I stated in my post that I used GDB to get the error message – Tobi Noara Jun 05 '22 at 04:59
  • &read instead of read raises an error ` note: expected 'LPDWORD' {aka 'long unsigned int *'} but argument is of type 'DWORD **' {aka 'long unsigned int **'}` – Tobi Noara Jun 05 '22 at 05:07
  • and `printf("Error reading file %s (%d)\n", argv[1], GetLastError());` literally never happens in the code I posted – Tobi Noara Jun 05 '22 at 05:12
  • @TobiNoara "*&read instead of read raises an error*" - you didn't change the *type* of `read` from `LPDWORD` to `DWORD`, like I showed. – Remy Lebeau Jun 05 '22 at 05:23
  • "*and `"Error reading file %s (%d)\n"` literally never happens in the code I posted*". - I know, and that is a bug. Your format string is wrong, for the reasons I stated. The string I proposed is the fix. – Remy Lebeau Jun 05 '22 at 05:28
  • Well I did that and it compiles without error, but the ACTUAL issue still persists – Tobi Noara Jun 05 '22 at 05:28
  • Also I don't need to restate what file it's reading – Tobi Noara Jun 05 '22 at 05:30
  • @TobiNoara the core dump issue you are asking about has NOTHING to do with the code you showed, and EVERYTHING to do with how you are using the debugger, which you did not explain. – Remy Lebeau Jun 05 '22 at 05:30
  • `gcc -g ./src./clt/main.c -o ./bin/clt.exe; gdb ./bin/clt \\.\\PhysicalDrive1` – Tobi Noara Jun 05 '22 at 06:01
  • @TobiNoara I have updated my answer to explain what is happening – Remy Lebeau Jun 05 '22 at 06:44