В качестве вступления: в Windows линии NT низкоуровневая работа с диском упрощена: достаточно получить дескриптор устройства с помощью функции CreateFile, и с диском можно работать как с файлом, используя стандартные функции ReadFile/WriteFile.
К примеру, чтобы получить дескриптор дисковода A: для чтения, достаточно сделать следующий вызов:
HANDLE hFile=CreateFile("\\\\.\\a:",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,0,NULL);
//И всё, можно работать
CloseHandle(hFile);
|
В Windows линии 9x этот подход не реализован: здесь нужно использовать стандартный драйвер vwin32.vxd, функции которого для работы с диском аналогичны соответствующим прерываниям MS-DOS. Дескриптор к драйверу получим с помощью функции CreateFile аналогично получению дескриптора диска в WinNT, для работы с драйвером задействуем функцию DeviceIoControl.
Как всегда, создаём новое приложение. Форма может выглядеть так:

Входные данные (номер диска, первый логический сектор, количество секторов для чтения) получаем через поля ввода. С помощью RadioGroup устанавливаем формат вывода считанных данных. Вся информация будет отображаться в компоненте класса TMemo.
Весь код заключён в обработчике нажатия на кнопку:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int drive=StrToIntDef(DriveNumberEdit->Text,-1),
startinglogicalsector=StrToIntDef(StartingSectorEdit->Text,-1),
numberofsectors=StrToIntDef(NumberSectorsEdit->Text,-1);
if(drive==-1 || startinglogicalsector==-1 || numberofsectors==-1)
{
MessageBox(Handle,"Error input parameters.",NULL,MB_OK|MB_ICONINFORMATION);
return;
}
if(!numberofsectors)
{
MessageBox(Handle,"You must specify at least 1 number of sectors to read.",
NULL,MB_OK|MB_ICONINFORMATION);
return;
}
PBYTE buff=(PBYTE)malloc(numberofsectors*512); //для чтения секторов
#pragma pack(1)
struct
{
DWORD StartingSector;
WORD NumberOfSectors;
DWORD pBuffer;
} ControlBlock;
#pragma pack()
#pragma pack(1)
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;
#pragma pack()
DIOC_REGISTERS reg;
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof vi; // это обязательно
GetVersionEx(&vi);
BOOL NT=(vi.dwPlatformId==VER_PLATFORM_WIN32_NT); //проверка на соответствие NT-платформе
HANDLE hFile;
if(!NT)
{
//используем драйвер vwin32
hFile=CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox(Handle,"Can't get handle of vwin32.vxd.",NULL,MB_OK|MB_ICONSTOP);
return;
}
ControlBlock.StartingSector=startinglogicalsector;
ControlBlock.NumberOfSectors=numberofsectors;
ControlBlock.pBuffer=(DWORD)buff;
// в SI помещаем: 0 - для чтения или 1 - для записи
// CX должно быть равно FFFFh для расширения 7305h прерывания int 21h
// DS:BX -> адрес структуры ControlBlock
// DL - номер диска (01h=A:, 02h=B: etc)
reg.reg_ESI=0;
reg.reg_ECX=-1;
reg.reg_EBX=(DWORD)&ControlBlock;
reg.reg_EDX=drive+1;
reg.reg_EAX=0x7305;
DWORD cb;
// 6 == VWIN32_DIOC_DOS_DRIVEINFO - вызываемая функция
BOOL result=DeviceIoControl(hFile,6,®,sizeof reg,®,sizeof reg,&cb,0);
if(!result || (reg.reg_Flags & 0x0001))return; //произошла ошибка
}
else
{
//WinNT
DWORD bytesread;
char drive_name[] = "\\\\.\\a:";
drive_name[4] += drive;
hFile=CreateFile(drive_name,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox(Handle,"Can't get handle of disk drive.",NULL,MB_OK|MB_ICONSTOP);
return;
}
SetFilePointer(hFile,512*startinglogicalsector,0,FILE_BEGIN);
if(!ReadFile(hFile,buff,numberofsectors*512,&bytesread,NULL))return;
}
CloseHandle(hFile);
Memo1->Clear();
AnsiString str="";
if(RadioGroup1->ItemIndex)
for(int i=0; i<numberofsectors*512; ++i)
str=str+IntToHex(buff[i],2)+" ";
else
{
MessageBox(Handle,"You selected TEXT output mode.\nAll symbols ASCII 0 will be replaced with spaces.",
NULL,MB_OK|MB_ICONINFORMATION);
//для того отобразить в Memo символы, следующие за символами с кодом 0
for(int i=0; i<numberofsectors*512; ++i)
if(!buff[i])buff[i]=0x20;
str=(char*)buff+'\0';
}
Memo1->Lines->Add(str);
free(buff);
}
|