I need to directly write to some physical device. I follow the indications given in the posts listed bellow and in the MSDN page bellow. But my code still fails in the function writeDisk(HANDLE hDevice)
with the error code:
[87] The parameter is incorrect
.
But the root of the problem doesn't appears to be there.
Beside that. When I unmount the device, it's no working (I can still access it from the system explorer), the same occur after locking it.
I have already checked the following links:
* Microsoft Docs: Calling DeviceIoControl
* StackOverflow: How to explicitly lock a mounted file system?
* StackOverflow: CreateFile: direct write operation to raw disk "Access is denied"
* StackOverflow: Can I get write access to raw disk sectors under Vista and Windows 7 in user mode?
But sadly, none of them works for me. The most useful threads are the first two.
Here is my code. Once you compile it you must run the application with administrator permissions in order to open the device with WRITE
access:
/* This program attempts to directly write to a device (without respecting the file system) */
#include <stdio.h>
#include <windows.h>
BOOL dismountDisk(HANDLE hDevice);
BOOL lockDisk(HANDLE hDevice);
BOOL writeDisk(HANDLE hDevice);
void getSystemMessageString(DWORD errorCode, char *decodedMessage, unsigned long size);
/* Main function
* Access the device
* Dismount the device
* Lock the device explicitly
* Write to the device
* Close handler
*/
int main()
{
/* Access the device */
HANDLE hDevice = CreateFileA(
"\\\\.\\PHYSICALDRIVE2", /* device id (get it with `$ wmic DISKDRIVE`) */
FILE_READ_DATA | FILE_WRITE_DATA, /* read/write access */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* shared */
NULL, /* default security attributes */
OPEN_EXISTING, /* only open if the device exists */
0, /* file attributes */
NULL); /* do not copy file attributes */
if (hDevice == INVALID_HANDLE_VALUE) { /* cannot open the physical drive */
fprintf(stderr, "Cannot open the device\n");
} else { /* dismount and lock */
BOOL result = dismountDisk(hDevice) && lockDisk(hDevice); /* try to dismount and lock the device */
if (!result) { /* device not dismounted/locked */
abort(); /* abort the operation */
} else { /* OK */
fprintf(stderr, "All OK. Check if the device has been dismounted and locked and press return to write.\n");
getchar();
writeDisk(hDevice); /* write to the disk */
}
CloseHandle(hDevice); /* close the handler to the device */
}
return 0;
}
/* Dismount disk */
BOOL dismountDisk(HANDLE hDevice)
{
DWORD unused;
BOOL b = DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
if (!b) {
DWORD errorCode = GetLastError();
char strBuff[500] = {0}; /* save the error message here */
getSystemMessageString(errorCode, strBuff, 500);
fprintf(stderr, "Error dismounting the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
}
return b;
}
/* Lock disk */
BOOL lockDisk(HANDLE hDevice)
{
DWORD unused;
BOOL b = DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
if (!b) {
DWORD errorCode = GetLastError();
char strBuff[500] = {0}; /* save the error message here */
getSystemMessageString(errorCode, strBuff, 500);
fprintf(stderr, "Error locking the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
}
return b;
}
/* Write disk */
BOOL writeDisk(HANDLE hDevice)
{
BYTE buffer[1000]; /* write 100 bytes */
DWORD bytesWritten; /* to get the total amount of bytes written */
BOOL b = WriteFile(hDevice, buffer, sizeof (buffer), &bytesWritten, NULL);
if (!b) {
DWORD errorCode = GetLastError();
char strBuff[500] = {0}; /* save the error message here */
getSystemMessageString(errorCode, strBuff, 500);
fprintf(stderr, "Error writting the device: [%lu] %s\n", errorCode, strBuff); /* print the error code and message */
} else {
fprintf(stderr, "%lu bytes written.\n", bytesWritten);
}
return b;
}
/* Convert the error code returned by GetLastError into a human-readable string */
void getSystemMessageString(DWORD errorCode, char *decodedMessage, unsigned long size)
{
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
decodedMessage, size + 1, NULL);
SetLastError(0); /* clear the last error */
}