CreateFile: operación de escritura directa al disco sin formato “Acceso denegado” – Vista, Win7

El documento de Microsoft relevante es:
Bloqueo de operaciones de escritura directa a volúmenes y discos
CreateFile, observaciones sobre discos físicos y volúmenes

El ejecutable está escrito en C ++ y llama a CreateFile() para abrir una tarjeta SD que no tiene ningún sistema de archivos . Las llamadas a GENERIC_READ CreateFile() y ReadFile() consecutivas son exitosas para GENERIC_READ sin privilegios de administrador.

CreateFile falla para GENERIC_WRITE incluso con privilegios de administrador. En el explorador, establezco Ejecutar como administrador en Propiedades> Compatibilidad> Nivel de privilegio. También traté de ejecutar el ejecutable desde un cmd de administrador (iniciado con Ctrl + Shift + Enter, “Administrador:” está en el título de la ventana, correctamente elevado). Aún así, recibo ERROR_ACCESS_DENIED (0x5).

¿Debo pasar algo más a CreateFile ? No tengo idea de qué atributos de seguridad son, simplemente paso NULL, el código relevante está aquí en la línea 92, y aquí en la línea 48.

¿O hay algo más que deba configurarse para ejecutar el proceso con privilegios de administrador?


A preguntas relacionadas:

¿Puedo obtener acceso de escritura en sectores de disco sin formato en Vista y Windows 7 en modo de usuario?
Acceso de partición sin formato en Windows Vista
¿Cómo obtener acceso directo a datos de HD sin procesar en C?
¿Hay alguna manera clara de obtener acceso exclusivo a una partición física en Windows?

Es bastante raro querer solo GENERIC_WRITE . Lo más probable es que quieras GENERIC_READ|GENERIC_WRITE .

Si bien la respuesta de @MSalters tiene sentido, no es así como funciona mi código. De hecho, es tan poco intuitivo, pasé varios días asegurándome de que el código funcionara.

Estos fragmentos de código se encuentran en un producto de software comprobado del mercado de consumo masivo. Cuando necesita modificar una estructura en disco, desmonta el volumen de win32 para que pueda modificar las estructuras del sistema de archivos NTFS o FAT. Curiosamente, el identificador de acceso de volumen es de solo lectura:

  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 } 

Si no puede obtener acceso de escritura a un volumen o partición, este código fuerza un desassembly si el usuario lo autoriza después de una advertencia de popa:

 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 } 

Escribir es bastante sencillo, excepto para posicionar el puntero de archivo por sector de 512 bytes:

  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; } 

Hay una nota en MSDN en la documentación de CreateFile:

El acceso directo al disco o a un volumen está restringido. Para obtener más información, consulte “Cambios en el sistema de archivos y la stack de almacenamiento para restringir el acceso directo al disco y el acceso directo al volumen en Windows Vista y en Windows Server 2008” en la Base de conocimiento de Ayuda y soporte en http://support.microsoft. com / kb / 942448 .

Se refiere a Vista / 2008, pero tal vez también se aplica a Win7.

Tuve un problema similar al portar desde el código x86 a x64. Menciona que está pasando null por su parámetro SECURITY_ATTRIBUTES; Obtuve errores de acceso denegado usando este enfoque hasta que realmente comencé a crear / pasar este parámetro.