Hace unas semanas comentaba con seoane que tras la publicación de dos artículos suyos sobre la lectura directa de discos FAT32, escribí un código en C/C++ añadiendo mas funcionalidad y compatible con FAT16 . No lo compatibilicé con FAT12 por el desuso actual de ese sistema de archivos. A Domingo le agradó mi interés en el tema y me animó a publicarlo. Así que quedé con seoane en impulsar un poco el tema, organizar y publicar el código, pero mis quehaceres me obligaron a posponerlo. Este tipo de código puede resultar peligroso para una unidad USB, así que me he tomado tiempo en realizar pruebas con distintos tipos de Pendrives pequeños
y grandes de hasta 32GB.
Como el tema que abrió seoane data de hace casi 2 meses, este mensaje se me alarga un poco y se centra en C/C++, me ha parecido oportuno abrir un nuevo tema y no continuar con el previo.
El código que presento lee directamente los dispositivos sin usar Streams, es compatible con FAT16 y 32, interpreta nombres largos de archivo, realiza imágenes de los dispositivos, las lee y es capaz de extraer archivos o carpetas, tanto de un disco como de un archivo de imagen. Estas últimas características pueden ser de utilidad a la hora de realizar copias de seguridad de las unidades con fines restauradores y para extraer el contenido de las mismas sin necesidad de restaurar una unidad.
El código está escrito en C/C++ en forma de API, no es OOP pero se podría escribir una clase con escasos cambios.
Acompaño una aplicación escrita en BCB6 que muestra el uso de la API y hace amigable este asunto, en un entorno gráfico con un TreeView, unos Memo y un ListView que representa un explorador gráfico. El programa detecta automáticamente la inserción de unidades USB y las coloca en un árbol, cuyo primer nivel es la unidad física y en el segundo, muestra la unidad lógica. La aplicación se podría complicar bastante mas...
Como curiosidad añadida, si recordáis el artículo de seoane en el que hablaba de cómo bloquear el acceso a un archivo autorun.inf, la APP de ejemplo usa la API que comento, para tratar los atributos de archivo FAT16/32 a bajo nivel realizando la tarea descrita en cualquier archivo o carpeta del disco. También podemos jugar con los atributos de directorio y archivo convirtiendo lo uno en lo otro y haciendo inaccesible los contenidos para Windows. En fin, es cuestión de jugar y experimentar.
He de advertir prudencia a la hora de restaurar imágenes de los pendrives, si equivocamos la unidad la machacaremos con la imagen convirtiéndola en otro pendrive... El programa avisará varias veces antes de escribir encima de una unidad de disco.
La API es fácil de usar. Primeramente debemos inicializar con la función OpenDisk que abre el disco físico o unidad lógica en cuestión. Precisa de un parámetro especial, un puntero a un tipo que he llamado ID_VOL y que almacenará el MBR, BMB, FAT y algunos datos mas de la unidad abierta. Este parámetro se precisará para el resto de las API y representa la unidad que hemos abierto. Al finalizar siempre deberemos llamar a CloseDisk con el consabido parámetro. El código está bastante documentado.
Un ejemplo simple en una aplicación de consola:
// Inicializamos y abrimos la unidad K: ID_VOL IdV; int Status = OpenDisk("\\\\.\\K:", &IdV, 0, false); // Leemos el Root Directory ListDir(&IdV, ""); // Leemos el Contenido de una carpeta: "K:\Mi Carpeta" ListDir(&IdV, "Mi Carpeta"); // Cambiando atributos ModifyAttr(&IdV, "Autorun.inf", ATTR_DEVICE, ATTR_DEVICE); // Terminamos... CloseDisk(&IdV);
Como la unidad abierta está representada por ID_VOL, se omite "K:\". Así, si damos una ruta como "Mi Carpeta" se entiende que es del directorio raíz; sin embargo "Mi Carpeta\archivo" entiende que archivo está en “Mi Carpeta” y que ésta se encuentra en el directorio raíz.
Una curiosidad final: el programa que presento es capaz de "trucar" una memoria USB de forma que parezca de un tamaño mucho mas grande del real. Hice una prueba volcando una imagen de un pendrive de 16 GB a a otro viejo de 500 Mb, imaginaros el resultado . Claro, esto como experimento o broma puede estar bien pero ese pendrive está un poco corrupto... ya lo restauraré.
Subo imágenes de la aplicación, el código fuente para BCB6 y el binario compilado.
Espero que el código y el programa sean de utilidad y sirvan de base para desarrollos futuros. Perdonarme si os aburre tanto C, si tengo mas tiempo procuraré migrar, al menos la API, a delphi, pero no prometo nada. Quizás algún valiente se atreva a hincarle el diente.
Saludos.
PD/ He adaptado el proyecto para que pueda ser compilado con bcb6pe.
Los platinos recordarán el hilo que inició cHackAll
PD2/ Por algún motivo desaparecieron los enlaces del código de NaviFat. Los adjunto con la última versión que guardo: 27-6-2012.