Ответ 1
Довольно редко требуется только GENERIC_WRITE
. Скорее всего, вы хотите GENERIC_READ|GENERIC_WRITE
.
Соответствующий документ Microsoft:
Блокировка операций прямого ввода в тома и диски
CreateFile, замечания по физическим дискам и томам
Исполняемый файл написан на С++ и вызывает CreateFile()
, чтобы открыть SD-карту с без файловой системы. CreateFile()
и последовательные вызовы ReadFile()
успешны для GENERIC_READ
без привилегий администратора.
CreateFile
завершается с ошибкой GENERIC_WRITE
даже с правами администратора. В проводнике я установил "Запуск от имени администратора" в разделе "Свойства" > "Совместимость" > "Уровень привилегий". Я также попытался запустить исполняемый файл с помощью cmd администратора (начатого с Ctrl + Shift + Enter, "Администратор:" находится в заголовке окна, правильно поднятом). Тем не менее, я получаю ERROR_ACCESS_DENIED
(0x5).
Должен ли я передать что-то еще на CreateFile
? Я понятия не имею, какие атрибуты безопасности, я просто передаю NULL, соответствующий код здесь в строке 92 и здесь в строке 48.
Или есть ли что-нибудь еще, что должно быть установлено для запуска процесса с правами администратора?
Могу ли я получить доступ на запись к секторам необработанного диска под Vista и Windows 7 в пользовательском режиме?
Необработанный доступ к разделам в Windows Vista
Как получить прямой доступ к необработанным данным HD в C?
Есть ли чистый способ получить эксклюзивный доступ к физическому разделу под Windows?
Довольно редко требуется только GENERIC_WRITE
. Скорее всего, вы хотите GENERIC_READ|GENERIC_WRITE
.
В то время как ответ @MSalters имеет смысл, это не то, как работает мой код. На самом деле это настолько противоречиво, что я провел несколько дней, убедившись, что код действительно работает.
Эти фрагменты кода находятся в проверенном программном продукте массового потребительского рынка. Когда ему нужно изменить структуру на диске, он отключает том win32, чтобы он мог изменять структуры файловой системы NTFS или FAT. Интересно, что дескриптор доступа к объему доступен только для чтения:
char fn [30];
snprintf (fn, sizeof fn, "\\\\.\\%s:", vol -> GetVolName ());
vol_handle = CreateFile (fn, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS,
NULL);
if (vol_handle == INVALID_HANDLE_VALUE)
{
// show error message and exit
}
Если вы не можете получить доступ на запись к тому или разделу, этот код принудительно отключается, если пользователь разрешает это после серьезного предупреждения:
if (!DeviceIoControl (vol_handle, FSCTL_DISMOUNT_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
DWORD err = GetLastError ();
errormsg ("Error %d attempting to dismount volume: %s",
err, w32errtxt (err));
}
// lock volume
if (!DeviceIoControl (vol_handle, FSCTL_LOCK_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
// error handling; not sure if retrying is useful
}
Написание тогда довольно просто, за исключением позиционирования указателя файла по 512-байтовому сектору:
long hipart = sect >> (32-9);
long lopart = sect << 9;
long err;
SetLastError (0); // needed before SetFilePointer post err detection
lopart = SetFilePointer (vol_handle, lopart, &hipart, FILE_BEGIN);
if (lopart == -1 && NO_ERROR != (err = GetLastError ()))
{
errormsg ("HWWrite: error %d seeking drive %x sector %ld: %s",
err, drive, sect, w32errtxt (err));
return false;
}
DWORD n;
if (!WriteFile (vol_handle, buf, num_sects*512, &n, NULL))
{
err = GetLastError ();
errormsg ("WriteFile: error %d writing drive %x sectors %lu..%lu: %s",
err, drv, sect, sect + num_sects - 1,
w32errtxt (err));
return false;
}
В MSDN имеется примечание в документации CreateFile:
Прямой доступ к диску или к тому ограничен. Для получения дополнительной информации см. "Изменения в файловой системе и стеке хранилища для ограничения прямого доступа к диску и прямого доступа к тому в Windows Vista и Windows Server 2008" в базе знаний справки и поддержки по адресу http://support.microsoft.com/kb/942448.
Это относится к Vista/2008, но, возможно, относится и к Win7.
У меня была аналогичная проблема при переносе с x86 на x64. Вы отмечаете, что передаете null
для своего параметра SECURITY_ATTRIBUTES; Я сам получал ошибки, связанные с доступом, используя этот подход, пока я не начал создавать/передавать этот параметр.