function VWin32(CtlCode: TVWin32CtlCode;
var Regs: TDiocRegisters): Boolean; // вспомогательная процедура
var
Device: THandle;
Count: LongWord;
begin
Device := CreateFile('\.\VWIN32', 0, 0, nil, 0,
FILE_FLAG_DELETE_ON_CLOSE, 0);
if Device = INVALID_HANDLE_VALUE then
raise Exception.Create(SysErrorMessage(GetLastError));
try
Result := DeviceIoControl(Device, Ord(CtlCode), @Regs,
SizeOf(Regs), @Regs, SizeOf(Regs), Count, nil);
finally
CloseHandle(Device) end end;
//само чтение
procedure ReadBoot95(Drive: Char; var Boot: TSector);
var
Regs: TDiocRegisters;
begin
with Regs do begin
EAX := Ord(UpCase(Drive)) - Ord('A');
EBX := LongWord(@Boot);
ECX := 1;
EDX := 0 end;
if not VWin32(ccVWin32Int25, Regs) then
raise Exception.Create(SysErrorMessage(GetLastError)) end;
//для NT, 2000, XP попроще
type
TSector = array[0..511] of Byte;
procedure ReadBootNT(Drive: Char; var Boot: TSector);
var
BytesRead: Cardinal;
H: THandle;
begin
H := CreateFile(PChar(Format('\.\%s:', [UpCase(Drive)])),
GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if H = INVALID_HANDLE_VALUE then
raise Exception.Create(SysErrorMessage(GetLastError));
try
if not ReadFile(H, Boot, SizeOf(Boot), BytesRead, nil)then
raise Exception.Create(SysErrorMessage(GetLastError));
finally
CloseHandle(H) end end;
// а юзать так
var
Boot: TSector;
begin
case Win32Platform of
VER_PLATFORM_WIN32_WINDOWS:
ReadBoot95(Drive, Boot);
VER_PLATFORM_WIN32_NT:
ReadBootNT(Drive, Boot) end;
Похвала автору за предоставленное рабочее решение, которое учитывает отличия между платформами Windows (95/98/ME и NT/2000/XP).
Теперь давайте разберемся в коде:
Процедура ReadBoot95
Эта процедура использует функцию VWin32 для чтения сектора загрузки с указанным диском. Она создает файловый обрабатчик с помощью API CreateFile и затем вызывает DeviceIoControl с параметрами:
Ord(UpCase(Drive))-Ord('A')// Буква диска (A-H)@Regs,SizeOf(Regs)// Указатель на регистры и размер регистровSizeOf(Boot),Count,nil// Буфер для данных сектора загрузки, длина и флаги
Функция VWin32 - это вспомогательная процедура, которая выполняет фактическое чтение операцию с помощью API Windows. Это довольно умно, чтобы обернуть эту логику в отдельную функцию.
Процедура ReadBootNT
Эта процедура использует API CreateFile снова для открытия указанного диска для чтения и затем вызывает ReadFile для чтения данных сектора загрузки в массив Boot:
PChar(Format('\.\%s:',[UpCase(Drive)]))// Путь к диск (например, `\.\C:`)GENERIC_READ,0,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0)// Опции открытия
Основной код
Основной код использует переменную Win32Platform для определения, какой платформе Windows соответствует, и вызывает либо ReadBoot95, либо ReadBootNT в зависимости от этого:
В целом, код хорошо структурирован и учитывает отличия между платформами Windows. Это хороший пример, как обрабатывать платформо-специфический код в Delphi.
Предложения
Рассмотрите добавление обработки ошибок для вызова ReadFile в процедуре ReadBootNT. Это поможет поймать любые потенциальные проблемы с чтением данных сектора загрузки.
Вам может понравиться использовать более надежный способ определения буквы диска (например, используя GetDriveLetters) вместо жесткого кодирования преобразования из верхнего регистра в целое число.
Если вы планируете использовать этот код для производства, вам может потребоваться добавить дополнительные проверки и валидации, чтобы обеспечить, что данные сектора загрузки являются валидными и согласуются между собой на различных платформах.
Также все! Надеюсь, это поможет, и счастливого программирования!
Программист может прочитать загрузочный сектор операционной системы, используя встроенные функции для чтения файла на платформах Windows 95, 98, Me и NT, 2000, XP.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.