¿Cómo bloquear explícitamente un sistema de archivos montado?

¿Cómo escribo en una unidad física en Windows 7?

Estoy tratando de escribir en un disco físico (p. Ej.\\.\PhysicalDrive0) en Windows 7.

Esta pregunta ha sido formuladaa muerte, pero nunca ha sido respondido. Es algo que solía funcionar en Windows XP, pero Microsoft rompió intencionalmente en Windows Vista. Microsoft proporciona pistas sobre cómo hacerlo, pero nadie ha podido resolverlo.

Solía funcionar

En los viejos tiempos, se permitía escribir en un disco físico (siempre que fuera administrador). El método para hacerlo incluso se documentó en un artículo de Knowledge Base:

INFORMACIÓN: Acceso directo a la unidad en Win32

Para abrir un disco duro físico para acceso directo al disco (E / S sin formato) en una aplicación basada en Win32, use un nombre de dispositivo del formulario

\\.\PhysicalDriveN

donde N es 0, 1, 2, y así sucesivamente, representando cada una de las unidades físicas en el sistema.

Puede abrir una unidad física o lógica utilizando la interfaz de programación de aplicaciones (API) CreateFile () con estos nombres de dispositivo siempre que tenga los derechos de acceso adecuados a la unidad (es decir, debe ser un administrador). Debe usar los indicadores CreateFile () FILE_SHARE_READ y FILE_SHARE_WRITE para obtener acceso a la unidad.

Todo eso cambió en Windows Vista, cuando se implementaron restricciones de seguridad adicionales.

¿Cómo se escribe en un disco físico?

Mucha gente, y muchas respuestas, en muchas preguntas de stackoverflow confunden:

escribir en un disco físico (p. ej.\\.\PhysicalDrive0) yescribir en un volumen lógico (p. ej.\\.\C$)

Microsoft toma nota de larestricciones impuestas a ambos tipos de operaciones:

Bloqueo de operaciones de escritura directa en volúmenes y discos

Escribir operaciones en un DASD (Dispositivo de almacenamiento de acceso directo.) la manecilla de volumentener éxito Si:

el sistema de archivos no está montado, o siLos sectores en los que se escribe son los sectores de arranque.Los sectores que se escriben para residir fuera del espacio del sistema de archivos.El sistema de archivos se ha bloqueado implícitamente al solicitar acceso de escritura exclusivo.El sistema de archivos se ha bloqueado explícitamente al enviar una solicitud de bloqueo / desmontaje.La solicitud de escritura ha sido marcada por un controlador en modo kernel que indica que esta verificación debe omitirse. El indicador se llama SL_FORCE_DIRECT_WRITE y está en el campo IrpSp-> flags. Este indicador lo verifican tanto el sistema de archivos como los controladores de almacenamiento.

En mi caso, estoy preguntando por escribir a unFísico, No unLógico uno. Microsoft observa el nuevo conjunto de restricciones para escribir en un controlador de disco físico:

Las operaciones de escritura en un identificador de disco tendrán éxito si:

Los sectores en los que se escribe no se incluyen en un sistema de archivos.Los sectores que se escriben caen dentro de un sistema de archivos montado que está bloqueado explícitamente.Los sectores que se escriben caen dentro de un sistema de archivos que no está montado o el volumen no tiene sistema de archivos.Mis sectores se escribenhacer caer dentro de un sistema de archivos -> fallarMis sectores se escribenhacer caer dentro del sistema de archivos montado, desbloqueado -> fallarMis sectores se escribenhacer caen dentro de un sistema de archivos que está montado, y dentro de un volumen lógico que tiene un sistema de archivos.

Los consejos sobre cómo hacerlo funcionar giran en torno a:

desmontar un sistema de archivosbloquear un sistema de archivos

Pero la pregunta es ¿cómo desmontar un sistema de archivos? ¿Cómo se bloquea un sistema de archivos?

¿Qué estas haciendo ahora?

Puedo leer todos los sectores físicos de un disco; eso no es un problema. El problema es cuando quieroescribir a un sector físico del disco.

El código actual que tengo es, en pseudocódigo:

void ZeroSector(Int64 PhysicalSectorNumber)
{
    String diskName := '\\.\PhysicalDrive0'; 

    DWORD desiredAccess := GENERIC_READ or GENERIC_WRITE;

    //INFO: Direct Drive Access Under Win32
    //https://support.microsoft.com/en-us/kb/100027
    //says you nedd both
    DWORD shareMode := FILE_SHARE_READ or FILE_SHARE_WRITE;

    //Open the physical disk
    hDisk := CreateFile(diskName, desiredAccess, shareMode,
            nil, OPEN_EXISTING, 0, 0);
    if hDisk = INVALID_HANDLE_VALUE
        RaiseLastWin32Error();
    try
    {
        Int32 bytesPerPhysicalSector := 4096; //Determined elsewhere using IOCTL_STORAGE_QUERY_PROPERTY+STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR

        //Setup buffer for what we will be writing
        Byte[] buffer = new Byte[bytesPerPhysicalSector];

        //Calculate the byte offset of where the sector is
        Int64 byteOffset = PhysicalSectorNumber * bytesPerPhysicalSector;

        //Seek to that byte offset
        SetFilePointer(hDisk, byteOffset.Lo, byteOffset.Hi, FILE_BEGIN); 

        //Write the buffer
        DWORD numberOfBytesWritten;
        if (!WriteFile(hDisk, buffer, bytesPerPhysicalSector, out numberOfBytesWritten, nil))
            RaiseLastWin32Error();
    }
    finally
    {
        CloseHandle(hDisk);
    }
}

Asombrosamente:

i puede abra el disco físico paraGENERIC_READ + GENERIC_WRITE acceso

no falla hasta que el actualWriteFile, que falla con:

ERROR: ACCESO DENEGADO

Cómo hacer lo que dice Microsoft

Microsoft dijo que mi escritura fallaría, y tenían razón. Dijeron que necesito bloquear explícitamente el sistema de archivos:

Las operaciones de escritura en un identificador de disco tendrán éxito si:

Los sectores que se escriben caen dentro de un sistema de archivos montado que está bloqueado explícitamente.

Excepto que no sé cómo hacer eso.

Sé que probablemente tenga que usarDeviceIoControl y uno de losIOCTLS a"bloquear" un volumen Pero eso presenta tres desafíos:

averiguar qué volúmenes están en el disco físico seleccionadoaveriguar qué IOCTL usaraveriguar cómo desbloquear los volúmenes bloqueados

Ignorando esos problemas, probé ciegamente elLockFile API Justo antes de llamarWriteFile:

//Try to lock the physical sector we will be writing
if (!LockFile(DiskHandle, byteOffset.Lo, byteOffset.Hi, bytesPerPhysicalSector, 0)
   RaiseLastWin32Error();

Eso falla con:

ERROR_INVALID_FUNCTION (1)

Respuestas a la pregunta(1)

Su respuesta a la pregunta