I'm trying to write to physical Hard Disk (SD Card/FAT32) directly using Windows API: WriteFile() but it always fails with ERROR_ACCESS_DENIED (0x5). I've tried many options suggested by some other posts such as unmount/lock but nothing seems to be working.
Does anyone have a better idea what is the root cause of this and how can we access to the physical drive directly from Windows API?
This is the sample code I'm using:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <windows.h>
DWORD lastError;
int main (void) {
uint16_t x, y;
uint8_t buffer[512];
DWORD bytesWritten, status;
HANDLE sdCardHandle = CreateFile("\\\\.\\PhysicalDrive2", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(sdCardHandle == INVALID_HANDLE_VALUE) {
CloseHandle(sdCardHandle);
return -1;
}
for (y = 1; y < 10001; y++) {
memset(buffer, y, sizeof(buffer));
if (WriteFile(sdCardHandle, buffer, sizeof(buffer), &bytesWritten, NULL) == 0) {
lastError = GetLastError();
printf("WriteFile error: 0x%X\n", lastError);
CloseHandle(sdCardHandle);
return -2;
}
printf("%d\n", y);
}
CloseHandle(sdCardHandle);
return 0;
}
Thanks!
Thanks all for the comments.
So I figured out a way to work around this problem (in Windows 10). The workaround is to lock, dismount and create disk as GPT to make Windows think it's unallocated disk. For whatever reason if it was formatted as FAT/FAT32, I just wouldn't be able to WriteFile to the card.
The following is the example code that is working for me:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <windows.h>
static CREATE_DISK raw; // dummy raw to create disk as GPT to trick Windows to see it as unallocated
static DWORD lastError;
static HANDLE sd_handle;
int main (void) {
uint16_t x, y;
uint8_t i, buffer[512];
DWORD bytes;
if ((sd_handle = CreateFile("\\\\.\\PhysicalDrive2",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL)) == INVALID_HANDLE_VALUE) {
printf("Error 0x%X openning Physical Drive\n", GetLastError());
return -1;
}
// Workaround to lock, dismount, and create disk as GPT to trick Windows to see drive as unallocated
if (!DeviceIoControl(sd_handle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytes, NULL)) {
puts("Error: Cannot lock volume");
CloseHandle(sd_handle);
return -2;
}
if (!DeviceIoControl(sd_handle, FSCTL_DISMOUNT_VOLUME , NULL, 0, NULL, 0, &bytes, NULL)) {
puts("Error: Cannot dismount volume");
CloseHandle(sd_handle);
return -3;
}
raw.PartitionStyle = PARTITION_STYLE_GPT;
if (!DeviceIoControl(sd_handle, IOCTL_DISK_CREATE_DISK, &raw, sizeof(raw), NULL, 0, &bytes, NULL)) {
puts("Error: Cannot create disk");
CloseHandle(sd_handle);
return -4;
}
// unlock, close, and reopen again to allow Windows to see it as newly unallocated drive
if (!DeviceIoControl(sd_handle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &bytes, NULL)) {
puts("Error: Cannot unlock volume");
CloseHandle(sd_handle);
return -5;
}
CloseHandle(sd_handle);
if ((sd_handle = CreateFile("\\\\.\\PhysicalDrive2",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL)) == INVALID_HANDLE_VALUE) {
printf("Error 0x%X openning Physical Drive\n", GetLastError());
return -6;
}
// Note for WriteFile:
// The GetLastError code ERROR_IO_PENDING is not a failure;
// it designates the write operation is pending completion asynchronously.
for (i = 1; i < 100; i++) {
memset(buffer, i, sizeof(buffer));
if (!WriteFile(sd_handle, buffer, sizeof(buffer), &bytes, NULL)
&&((lastError = GetLastError()) != ERROR_IO_PENDING)) {
printf("WriteFile error: 0x%X\n", lastError);
CloseHandle(sd_handle);
return -7;
}
}
}
Again, this is just a workaround that I found out to be working for me, but I don't know what was the exact cause yet. If anyone knows the root cause and is willing to share that would be great.