В качестве вступления: в 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); } |