windowswinapiio

How to read a raw disk without locking/dismounting the volume, using Win32 API?


This StackOverflow question has an answer that requires the volume to be locked/dismounted, but it seems this is not necessarily required. When I use the hex editor HxD (Tools > Open disk) to open a volume (logical disks) or a physical disk, I can open C: and even the SSD it is in seamlessly. I can keep using the C drive without problems, and HxD updates its content.

Also, when I use MSVC, with fopen("\\\\.\\D:", "rb") and fgetc(), I am able to read the first byte of the raw disk/volume D:. This also happens with MinGW, which I think links to MSVC's library.

So, how can I do this using the Win32 API? Or is MSVC doing sinister things that are not normally done by the Win32 API?


Solution

  • As @RbMm said, CreateFile("\\\\.\\D:", ...) can make it just as fopen("\\\\.\\D:", "rb"). This is nothing related to MinGW and MSVC.

    When using the flag FILE_FLAG_NO_BUFFERING, which is implicit for devices, the size and offset of data must be a multiple of the sector size. For example,

    #include <windows.h>
    #include <stdio.h>
    
    #define SECTOR_SIZE 512
    
    int main()
    {
            HANDLE hFile;
            unsigned char buf[SECTOR_SIZE];
            DWORD rd;
            hFile = CreateFile(
                    "\\\\.\\D:", 
                    /* "GENERIC_WRITE" for writing access. */
                    GENERIC_READ,
                    /* Necessary to allow other programs to read and write to the
                     * device.
                     */
                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL
            );
            if (hFile == INVALID_HANDLE_VALUE) {
                    fprintf(stderr, "Cuuld not open file: %lu\n", GetLastError());
                    return 1;
            }
    
            if (ReadFile(hFile, buf, SECTOR_SIZE, &rd, NULL) == FALSE) {
                    fprintf(stderr, "Could not read file: %lu\n", GetLastError());
                    CloseHandle(hFile);
                    return 1;
            }
            for (size_t i = 0; i < SECTOR_SIZE; i++)
                    printf("%X ", buf[i]);
    
            CloseHandle(hFile);
            return 0;
    }