2012-01-01 8 views
15

El documento relevante Microsoft es:
Blocking Direct Write Operations to Volumes and Disks
CreateFile, remarks on Physical Disks and VolumesCreateFile: operación de escritura directa a disco sin procesar "Acceso denegado" - Vista, Win7

El ejecutable está escrito en C++ y se llama CreateFile() para abrir una tarjeta SD tarjeta que tiene sin sistema de archivos. Las llamadas 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í, obtengo ERROR_ACCESS_DENIED (0x5).

¿Tengo que pasar algo más al CreateFile? no tengo idea de lo que son los atributos de seguridad, acabo de pasar null, relevant code is here en la línea 92, y en la línea 48. here

O ¿hay algo más que debe ser configurado para ejecutar el proceso con privilegios de administrador?


preguntas Un relacionadas:

Can I get write access to raw disk sectors under Vista and Windows 7 in user mode?
Raw partition access in Windows Vista
How to obtain direct access to raw HD data in C?
Is there a clean way to obtain exclusive access to a physical partition under Windows?

+0

Si no hay un sistema de archivos crear el archivo debe fallar. Quizás con la lectura no falla hasta que lee al menos un byte, en contraste con escribir, que intenta crear un archivo real (vacío) en abierto. –

+3

@DannyVarod La lectura funciona como un encanto, he leído gran cantidad de datos y los datos son correctos. Consulte [Microsoft's doc] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx#physical_disks_and_volumes), 'CreateFile' ** es la forma de manejar unidades sin sistema de archivos. ** – Ali

+0

¿Qué valor se pasa como el parámetro * access * a 'open_device()'? – wallyk

Respuesta

13

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

+1

OK, ese era el problema :) ¿Podrían explicarme por qué? – Ali

+5

No es 100% seguro, no revisó todo el código. Muchas operaciones de estilo "modificar" funcionan leyendo un gran fragmento de datos, alterando el bit que desean y volviendo a escribir todo el fragmento. P.ej. no se puede escribir físicamente un byte en un disco duro, pero los sistemas de archivos pretenden que se puede. Obviamente necesitas permisos de lectura y escritura para eso. – MSalters

+0

Puede valer la pena señalar que las tarjetas SD tienen un tamaño de bloque inusualmente grande, típicamente 128k. No sé cómo maneja Windows esto a un nivel bajo, pero puede ser que necesite el acceso de lectura para escribir cantidades más pequeñas que esto (a nivel de hardware, podría leer 128k en la memoria, cambiar la parte necesita cambiar, borrar el bloque y volver a escribirlo; es posible que el kernel de Windows decida que se requiere acceso de lectura para realizar esta operación aunque la lectura no haya sido iniciada por el código de nivel de usuario). – Jules

1

No hay nota en MSDN en la documentación de CreateFile:

acceso directo al disco o un volumen es restringido. Para obtener más información, consulte "Cambios en el sistema de archivos y la pila 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 conocimientos 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.

+0

He leído eso, pero ¿qué debo hacer? ¿Cuál es el problema? En el documento, leo esto "** Los cambios ** en el sistema de archivos y en la pila de almacenamiento ** no se aplican ** si el volumen no es montado o ** si el volumen no tiene un sistema de archivos. ** "En mi caso no hay un sistema de archivos. – Ali

0

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

+0

Desafortunadamente, solo tengo el código VB.NET para mostrar, y como estoy usando el framework .NET es probablemente sea una pérdida de tiempo publicarlo, pero díganme si desean que lo haga. – Sukasa

15

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 mango de acceso volumen es de sólo 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 obliga a desmontar si el usuario autoriza tal después de una severa advertencia:

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 
} 

la escritura es entonces bastante sencillo, excepto para posicionar el puntero del archivo de 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; 
    } 
+1

Lo siento, ya había otorgado la recompensa cuando noté su respuesta. De todos modos, ¿podría hacer que su respuesta sea más explícita, por favor? ¿Estás tratando de decir que GENERIC_READ solo podría ser suficiente para obtener acceso de escritura? – Ali

+0

@Ali: GENERIC_READ solo es el caso. Las operaciones subsiguientes de escritura funcionan bien una vez que el bloqueo es exitoso. En cuanto a los puntos, ¿tal vez podrías votarlo? :-) – wallyk

+0

Sí, lamento mucho la recompensa, he votado a favor de tu pregunta. Intentaré con lo que escribas, y si realmente funciona, agregaré una nota al final de la pregunta. Eso es lo mejor que puedo hacer ahora ... – Ali

Cuestiones relacionadas