Esta es mi duda hace un tiempo que estoy buscando y no termino de dar en el clavo. Hasta donde se los archivos no desaparecen por completo de un disco cuando son eliminados. Quiero acceder al disco en forma RAW para buscar archivos eliminados. No quiero un programa para hacerlo, quiero programarlo yo. Se que con el api CreateFile() se puede acceder a una unidad de disco, después estoy dando vueltas y no termino de leer nada del disco. Busco info sobre DeviceIOControl() pero no me termina siendo clara y hay muchas constantes para las que no encuentro los valores numericos ni muchos ejemplos de codigo (eso seria lo mejor) después creo haber visto y perdido un ejemplo donde utilizaba las mismas funciones para leer un fichero pero con el disco. En fin un ejemplo seria lo mejor pero una ayuda cualquiera sea no seria despreciada. Gracias.
fijate esta clase, la saqué no recuerdo de donde... je :P
#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#define VWIN32_DIOC_DOS_IOCTL 1 // specified MS-DOS device I/O ctl - Interrupt 21h Function 4400h - 4411h
#define VWIN32_DIOC_DOS_INT25 2 // Absolute Disk Read command - Interrupt 25h
#define VWIN32_DIOC_DOS_INT26 3 // Absolute Disk Write command - Interrupt 25h
#define VWIN32_DIOC_DOS_INT13 4 // Interrupt 13h commands
#define VWIN32_DIOC_SIMCTRLC 5 // Simulate Ctrl-C
#define VWIN32_DIOC_DOS_DRIVEINFO 6 // Interrupt 21h Function 730X commands
#define CARRY_FLAG 1
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER (DWORD)-1
#endif
typedef struct _DISKIO {
DWORD dwStartSector; // starting logical sector number
WORD wSectors; // number of sectors
DWORD dwBuffer; // address of read/write buffer
} DISKIO, * PDISKIO;
typedef struct _DIOC_REGISTERS
{
DWORD reg_EBX;
DWORD reg_EDX;
DWORD reg_ECX;
DWORD reg_EAX;
DWORD reg_EDI;
DWORD reg_ESI;
DWORD reg_Flags;
} DIOC_REGISTERS, *PDIOC_REGISTERS;
struct partial_boot_sector_info{
LPSTR Fs;
DWORD FsOffs;
DWORD SerialOffs;
};
class DiskSectorRW{
public:
virtual bool Open(char *vol) = 0;
virtual void Close() = 0;
virtual bool ReadSector(DWORD sector, char *Buffer, int sectorSize = 512) = 0;
virtual bool WriteSector(DWORD sector, char *buffer, int sectorSize = 512) = 0;
};
class DiskSectorWinNT : public DiskSectorRW
{
private:
HANDLE m_hDisk;
public:
bool Open(char *vol);
void Close();
bool ReadSector (DWORD sector, char *Buffer, int sectorSize = 512);
bool WriteSector(DWORD sector, char *Buffer, int sectorSize = 512);
};
class DiskSectorWin9x : public DiskSectorRW
{
private:
HANDLE m_hVmm32;
bool m_bOpened;
char m_chDrive;
BYTE m_nDriveNo;
bool m_bW9xOsr2AndAbove;
bool m_bUseLocking;
public:
DiskSectorWin9x() : m_bUseLocking(false) { }
bool Open(char *vol);
void Close();
bool ReadSector (DWORD sector, char *Buffer, int sectorSize = 512);
bool WriteSector(DWORD sector, char *Buffer, int sectorSize = 512);
static bool LockLogicalVolume (HANDLE hVWin32, BYTE bDriveNum, BYTE bLockLevel, WORD wPermissions);
static bool UnlockLogicalVolume(HANDLE hVWin32, BYTE bDriveNum);
static bool ReadLogicalSectors (HANDLE hDev, BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff);
static bool WriteLogicalSectors (HANDLE hDev, BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff);
static bool NewReadSectors(HANDLE hDev, BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff);
static bool NewWriteSectors(HANDLE hDev, BYTE bDrive, DWORD dwStartSector, WORD wSectors, LPBYTE lpSectBuff);
};
class DiskSector
{
private:
DiskSectorRW *util;
public:
DiskSector();
~DiskSector();
bool Open(char *vol);
void Close();
bool ReadSector(DWORD sector, char *Buffer, int sectorSize = 512);
bool WriteSector(DWORD sector, char *buffer, int sectorSize = 512);
};
#include "disk.h"
DiskSector::DiskSector()
{
if (GetVersion() > 0x80000000)
util = new DiskSectorWin9x;
else
util = new DiskSectorWinNT;
}
void DiskSector::Close()
{
util->Close();
}
bool DiskSector::Open(char *vol)
{
return util->Open(vol);
}
bool DiskSector::WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
return util->WriteSector(sector, Buffer, sectorSize);
}
bool DiskSector::ReadSector(DWORD sector, char *Buffer, int sectorSize)
{
return util->ReadSector(sector, Buffer, sectorSize);
}
DiskSector::~DiskSector()
{
delete util;
}
/***********************************************************/
bool DiskSectorWinNT::Open(char *vol)
{
char szDrive[10];
sprintf(szDrive
, "\\\\.\\%c:", vol
[0]); m_hDisk = ::CreateFile(
szDrive,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
return m_hDisk != INVALID_HANDLE_VALUE;
}
void DiskSectorWinNT::Close()
{
if (m_hDisk != INVALID_HANDLE_VALUE)
::CloseHandle(m_hDisk);
}
bool DiskSectorWinNT::ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
DWORD read = 0;
if (::SetFilePointer(m_hDisk, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;
if (!::ReadFile(m_hDisk, Buffer, sectorSize, &read, NULL))
return false;
return true;
}
bool DiskSectorWinNT::WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
DWORD wrote = 0;
if (::SetFilePointer(m_hDisk, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;
if (!::WriteFile(m_hDisk, Buffer, sectorSize, &wrote, NULL))
return false;
return true;
}
/***********************************************************/
bool DiskSectorWin9x::Open(char *vol){
m_bOpened = false;
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!::GetVersionEx((OSVERSIONINFO *)&osvi)){
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!::GetVersionEx ((OSVERSIONINFO *)&osvi))
return false;
}
if (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
return false;
m_nDriveNo = m_chDrive - 'A' + 1;
char temp[10] = {0};
if (::GetDriveType(temp) != DRIVE_FIXED)
return false;
m_bW9xOsr2AndAbove = (osvi.dwMajorVersion >= 4 && osvi.dwMinorVersion >= 10)
||
(
(osvi.dwBuildNumber == 4 && osvi.dwMinorVersion == 0) &&
(osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
);
m_hVmm32 = ::CreateFile(
"\\\\.\\VWIN32", // name
0, // access mode
0, // share mode
NULL, // security descriptor
0, // ho to create
FILE_FLAG_DELETE_ON_CLOSE, // file attributes
NULL); // handle to file with att to copy
m_bOpened = (m_hVmm32 != INVALID_HANDLE_VALUE);
return m_bOpened;
}
void DiskSectorWin9x::Close()
{
if (m_bOpened)
::CloseHandle(m_hVmm32);
m_bOpened = false;
}
bool DiskSectorWin9x::ReadLogicalSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio = {0};
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = bDrive - 1; // Int 25h drive numbers are 0-based.
reg.reg_EBX = (DWORD)&dio; // Drive letter 0 = A, 1 = B 2 = C ect..
reg.reg_ECX = 0xFFFF; // use DISKIO struct
fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT25,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the read succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult == TRUE;
}
bool DiskSectorWin9x::WriteLogicalSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio = {0};
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = bDrive - 1; // Int 26h drive numbers are 0-based.
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = 0xFFFF; // use DISKIO struct
fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT26,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult == TRUE;
}
bool DiskSectorWin9x::NewReadSectors(HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio;
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = (DWORD)-1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based
fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the read succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult == TRUE;
}
bool DiskSectorWin9x::NewWriteSectors(HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio;
dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = (DWORD)-1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based
reg.reg_ESI = 0x6001; // Normal file data/write (See function
// documentation for other values)
fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult == TRUE;
}
bool DiskSectorWin9x::LockLogicalVolume (HANDLE hVWin32,
BYTE bDriveNum,
BYTE bLockLevel,
WORD wPermissions)
{
BOOL fResult;
DIOC_REGISTERS regs = {0};
BYTE bDeviceCat; // can be either 0x48 or 0x08
DWORD cb;
bDeviceCat = 0x48;
ATTEMPT_AGAIN:
// Set up the parameters for the call.
regs.reg_EAX = 0x440D;
regs.reg_EBX = MAKEWORD(bDriveNum, bLockLevel);
regs.reg_ECX = MAKEWORD(0x4A, bDeviceCat);
regs.reg_EDX = wPermissions;
fResult = ::DeviceIoControl (hVWin32, VWIN32_DIOC_DOS_IOCTL,
®s, sizeof(regs), ®s, sizeof(regs),
&cb, 0);
fResult = fResult && !(regs.reg_Flags & CARRY_FLAG);
if (!fResult && (bDeviceCat != 0x08)){
bDeviceCat = 0x08;
goto ATTEMPT_AGAIN;
}
return fResult == TRUE;
}
bool DiskSectorWin9x::UnlockLogicalVolume (HANDLE hVWin32, BYTE bDriveNum)
{
BOOL fResult;
DIOC_REGISTERS regs = {0};
BYTE bDeviceCat; // can be either 0x48 or 0x08
DWORD cb;
bDeviceCat = 0x48;
ATTEMPT_AGAIN:
regs.reg_EAX = 0x440D;
regs.reg_EBX = bDriveNum;
regs.reg_ECX = MAKEWORD(0x6A, bDeviceCat);
fResult = ::DeviceIoControl (hVWin32, VWIN32_DIOC_DOS_IOCTL,
®s, sizeof(regs), ®s, sizeof(regs),
&cb, 0);
fResult = fResult && !(regs.reg_Flags & CARRY_FLAG);
if (!fResult && (bDeviceCat != 0x08)){
bDeviceCat = 0x08;
goto ATTEMPT_AGAIN;
}
return fResult == TRUE;
}
bool DiskSectorWin9x::ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
if (!m_bOpened)
return false;
if (m_bUseLocking)
{
if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 1, 1))
return false;
if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 2, 0))
{
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
return false;
}
}
bool bRet;
if (m_bW9xOsr2AndAbove)
bRet = NewReadSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE)Buffer);
else
bRet = ReadLogicalSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE)Buffer);
if (m_bUseLocking)
{
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
}
return bRet;
}
bool DiskSectorWin9x::WriteSector (DWORD sector, char *Buffer, int sectorSize)
{
if (!m_bOpened)
return false;
if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 1, 1))
return false;
if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 2, 0))
{
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
return false;
}
if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 3, 0))
{
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
return false;
}
bool bRet;
if (m_bW9xOsr2AndAbove)
bRet = NewWriteSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE) Buffer);
else
bRet = WriteLogicalSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE) Buffer);
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
return bRet;
}
S2
PD: cabe aclarar que tenes que tener permisos administrativos al usar el código.
PD2: con esto solo accedes al los datos raw del disco, luego tenes que analizar la cabecera de las particiones, detectar el tipo (FAT, NTFS) y según eso ver la lista de nodos de archivos... en google había visto algunos ejemplos hace un tiempo.
Gracias. Voy a ver si puedo crear una dll y subirla en agradecimiento. ;-)