Читаем и пишем сектора диска
Сразу предупреждаю: прямая запись секторов на диск - дело опасное. Поэтому любые эксперименты оставляю на Ваш страх и риск. Не уверены, не лезьте.
Ответы на вопросы по переменным и типам, используемым в коде, вероятнее всего, Вы найдете тут.
Код Delphi:
// так как диск для нас - это единый файл, то для перемещения по нему // с помощью SetFilePointer понадобится 64хразрядная арифметика function __Mul(a,b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD asm mul edx mov [ecx],edx end;
Для чтения нам понадобиться поток (если, конечно, Вы не относитесь к числу любителей "подвисания" программы на сбойных секторах).
Код Delphi:
type TReadThread = class(TThread) private { Private declarations } protected Flag: boolean; DriveNumber: byte; StartingSector: DWORD; SectorCount: DWORD; Buffer: Pointer; BytesPerSector: DWORD; OutData: DWORD; hFile: THandle; ovrDisk: TOverlapped; procedure PostRead; procedure Execute; override; end;
Код Delphi:
procedure TReadThread.Execute; var br,br1,TmpLo,TmpHi: DWORD; TimeOut:boolean; WFSO: DWORD; begin Flag:=true; FillChar(ovrDisk,SizeOf(ovrDisk),0); ovrDisk.hEvent := CreateEvent(nil, False, False, nil); hFile := CreateFile(PChar('\\.\PhysicalDrive'+IntToStr(DriveNumber)), GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED or FILE_FLAG_NO_BUFFERING,0); if hFile = INVALID_HANDLE_VALUE then Exit; TmpLo := __Mul(StartingSector,BytesPerSector,TmpHi); if SetFilePointer(hFile,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then begin SectorCount := SectorCount*BytesPerSector; TimeOut:=false; ResetEvent(ovrDisk.hEvent); ovrDisk.Offset:=TmpLo; ovrDisk.OffsetHigh:=TmpHi; if (not(ReadFile(hFile,Buffer^,SectorCount,br,@ovrDisk))) then begin if (GetLastError()<>ERROR_IO_PENDING) then OutData:=0 else begin repeat WFSO:=WaitForSingleObject(ovrDisk.hEvent,1000*ReadTimeOut); if (WFSO=WAIT_ABANDONED) then TimeOut:=true; if (WFSO=WAIT_FAILED) then TimeOut:=true; if (WFSO=WAIT_TIMEOUT) then TimeOut:=true; Application.ProcessMessages; until (TimeOut or (WFSO=WAIT_OBJECT_0) or (not(InWork))); if TimeOut then OutData:=0 else OutData:=SectorCount; end; end; end; CloseHandle(hFile); CloseHandle(ovrDisk.hEvent); Flag:=false; end;
Теперь можно приступать и к чтению/записи секторов
Код Delphi:
function TForm1.ReadSectors(DriveNumber: Byte; StartingSector, SectorCount: DWORD; Buffer: Pointer; BytesPerSector: DWORD = 512): DWORD; begin Result := 0; ReadThread:=TReadThread.Create(true); ReadThread.Priority:=tpNormal; ReadThread.DriveNumber:=DriveNumber; ReadThread.StartingSector:=StartingSector; ReadThread.SectorCount:=SectorCount; ReadThread.Buffer:= Buffer; ReadThread.BytesPerSector:=BytesPerSector; ReadThread.FreeOnTerminate:=false; ReadThread.Execute; while ReadThread.Flag do Application.ProcessMessages; Result:=ReadThread.OutData; ReadThread.Destroy; end; function TForm1.WriteSectors(DriveNumber: Byte; StartingSector, SectorCount: DWORD; Buffer: Pointer; BytesPerSector: DWORD = 512): DWORD; var hFile: THandle; bw,TmpLo,TmpHi: DWORD; begin Result := 0; hFile := CreateFile(PChar('\\.\PhysicalDrive'+IntToStr(DriveNumber)), GENERIC_WRITE,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if hFile = INVALID_HANDLE_VALUE then Exit; TmpLo := __Mul(StartingSector,BytesPerSector,TmpHi); if SetFilePointer(hFile,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then begin SectorCount := SectorCount*BytesPerSector; if WriteFile(hFile,Buffer^,SectorCount,bw,nil) then Result := bw; end; CloseHandle(hFile); end;
Оставьте свой комментарий
Войдите, чтобы оставлять комментарии
Оставить комментарий как гость