IntToHex значений в 512-байтовом массиве, относящемся к дескриптору CreateFile, всегда возвращает один и тот же результат? Синтаксис FreePascal\Delphi.

Короче говоря, моя программа позволяет хэшировать вещи. Единственное, чего в настоящее время ему не хватает, — это возможности хешировать физические диски в версии для Windows (версия для Linux позволяет пользователю выбирать /dev/sda и т. д.).

Я создал кнопку, которая при нажатии отображает список подключенных устройств, чтобы дать мне "\.\PHYSICALDISKX" (благодаря предложениям пользователей SO в ответ на мои предыдущие сообщения). Затем я могу передать это значение функции Windows API CreateFile, когда пользователь дважды щелкнет по нему, чтобы создать для него дескриптор как событие двойного щелчка ListBox. Итак, я сделал все это. Код ниже относится.

Тем не менее, я хочу проверить, работает ли установленный мной дескриптор CreateFile — оператор if предполагает, что это так, но мне нужно проверить, действительно ли я могу читать данные для передачи другим моим функциям. Чтобы проверить это, я пытаюсь прочитать первые 512 байт любого заданного диска и «быстро» отобразить его в блоке заметок. Тем не менее, я не могу в жизни понять, почему мой вывод неверен, а это так. Я получаю некоторые шестнадцатеричные значения, но это не те шестнадцатеричные значения, которые присутствуют в первых 512 байтах. И это всегда один и тот же список шестнадцатеричных значений, независимо от того, на какой диск я смотрю! Поэтому я понятия не имею, откуда берутся эти значения или почему они всегда одинаковы. Вся идея заключается в том, чтобы я проверил, что мой дескриптор в порядке, и что я действительно могу читать данные с диска, чтобы затем передать их своим функциям хеширования.

Кто-нибудь может увидеть, где я ошибаюсь, пожалуйста?

procedure TForm1.ListBox1DblClick(Sender: TObject);
var
   listBox : TListBox;
   index   : Integer;
   hDiskToHash, i : integer;
   DiskHashValue, DiskToHashFileName, TmpStr : string;
   RawMBR : array [0..511] of byte;
   bytesread : DWORD;
 begin
   i := 0;
   // Cast the passed object to its correct type
   listBox := TListBox(Sender);

   // Get the index of the selected list item
   index   := listBox.ItemIndex;

   // Display the selected list item value
   ShowMessage(listBox.Items[index]);

   // sValue1 is a global variable containing string '\\.\PHYSICALDISKX', populated by procedure TForm1.GetWin32_DiskDriveInfo;
   hDiskToHash := Windows.CreateFile(PChar(sValue1), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
   if hDiskToHash <> INVALID_HANDLE_VALUE then
   begin
      SetFilePointer(hDiskToHash,512 * 0,nil,FILE_BEGIN); // replace 0 with sector that you wish to read
      ReadFile(hDiskToHash, RawMBR[0], SizeOf(RawMBR), bytesread, nil);
      for i := Low(RawMBR) to High(RawMBR) do
        begin
        Memo2.Lines.Add(IntToHex(RawMBR[i],2)); // Add each hex byte on a new line
        end;
      CloseHandle(hDiskToHash);
   end
   else
   begin
    ShowMessage('Failed to open '+sValue1);
   end;
 end; 

person Gizmo_the_Great    schedule 01.02.2012    source источник
comment
Попробуйте добавить флаг FILE_READ_ATTRIBUTES в CreateFile. Также, если вы хотите прочитать MBR, вы должны использовать функцию DeviceIoControl, передавая значение IOCTL_DISK_GET_PARTITION_INFO   -  person RRUZ    schedule 02.02.2012
comment
Откуда вы знаете, что первые 512 байт дисков различны? Кроме того, поскольку вы подозреваете, что что-то не так, почему вы не проверяете возвращаемые значения функций API? Вы не проверяете, удалось ли ReadFile успешно или сколько байтов было действительно прочитано.   -  person Rob Kennedy    schedule 02.02.2012
comment
Этот бит включен в GENERIC_READ, @Rruz.   -  person Rob Kennedy    schedule 02.02.2012
comment
Роб - честные очки! Как дурак, я не понял, что ReadFile возвращает истинное или ложное логическое значение. Я добавил его как if then, и он не выполняется, поэтому должен возвращать false. Итак, мой ReadFile не работает, во-первых. Что касается того, как я узнаю, что они не совпадают - у меня есть другой шестнадцатеричный редактор, и я смотрю на 3 разных физических диска и вижу, что они имеют разные 512 байтов в секторе 0.   -  person Gizmo_the_Great    schedule 02.02.2012
comment
Только что заметил - FILE_FLAG_RANDOM_ACCESS для CreateFile. API Windows указывает, что FILE_FLAG_RANDOM_ACCESS предназначен для случайного доступа! Не тот случай для меня. Я изменю это и посмотрю, что произойдет!   -  person Gizmo_the_Great    schedule 02.02.2012
comment
Нет - все равно радости нет. Изменили строку CreateFile следующим образом: hDiskToHash := Windows.CreateFile(PChar(sValue1), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); в соответствии с msdn.microsoft .com/en-us/library/windows/desktop/, но ReadFile по-прежнему имеет значение false. :-( RRUZ - Комментарий 1 - правда ли это, даже если я хочу, чтобы моя программа читала весь диск, от раздела 0 до самого конца в режиме только для чтения? Если это так, это может меня немного испортить! Я не знаю, как я буду передавать некоторые сектора в одну сторону, а другие - в другую, в мои процедуры хеширования.   -  person Gizmo_the_Great    schedule 02.02.2012
comment
Я не уверен, что вы понимаете, что означают эти флаги. Посмотрите сообщение Рэймонда о.   -  person EMBarbosa    schedule 02.02.2012
comment
В ПОРЯДКЕ. Вы определили, что ReadFile возвращает ноль. Следующий шаг — позвонить GetLastError, чтобы узнать, что пошло не так. В документации так сказано. Вы получите код ошибки. Найдите этот номер в таблицах в MSDN. Кроме того, не забудьте использовать символ @ перед нашими именами, чтобы мы были уведомлены, когда вы ответите нам.   -  person Rob Kennedy    schedule 02.02.2012


Ответы (1)


На какой версии Windows вы работаете? В документации CreateFile() указано:

Прямой доступ к диску или к тому ограничен. Дополнительные сведения см. в разделе «Изменения в файловой системе и стеке хранилища для ограничения прямого доступа к диску и прямого доступа к тому в Windows Vista и Windows Server 2008» в базе знаний справки и поддержки по адресу http://support.microsoft.com/kb/942448.

С учетом сказанного попробуйте следующее:

procedure TForm1.ListBox1DblClick(Sender: TObject); 
var 
  listBox : TListBox; 
  index   : Integer; 
  hDiskToHash: THandle;
  i : integer; 
  RawMBR : array [0..511] of Byte; 
  Offset, BytesRead : DWORD; 
begin 
  // Cast the passed object to its correct type 
  listBox := TListBox(Sender); 

  // Get the index of the selected list item 
  index := listBox.ItemIndex; 
  if index = -1 then Exit;

  // Display the selected list item value 
  ShowMessage(listBox.Items[index]); 

  // sValue1 is a global variable containing string '\\.\PHYSICALDISKX',
  // populated by procedure TForm1.GetWin32_DiskDriveInfo; 
  hDiskToHash := Windows.CreateFile(PChar(sValue1), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0); 
  if hDiskToHash = INVALID_HANDLE_VALUE then RaiseLastOSError;
  try
    Offset := 512 * 0; // replace 0 with sector that you wish to read 

    if (SetFilePointer(hDiskToHash, Offset, nil, FILE_BEGIN) <> Offset) then raise Exception.Create("Did not seek to sector 0 correctly!");

    if not ReadFile(hDiskToHash, RawMBR[0], SizeOf(RawMBR), BytesRead, nil) then RaiseLastOSError;
    if BytesRead <> SizeOf(RawMBR) then raise Exception.Create("Did not read the full MBR!");

    for i := 0 to BytesRead-1 do 
    begin 
      Memo2.Lines.Add(IntToHex(RawMBR[i], 2)); // Add each hex byte on a new line 
    end; 
  finally
    CloseHandle(hDiskToHash); 
  end;
end;  
person Remy Lebeau    schedule 02.02.2012
comment
В последнее время мы пишем слишком много кода на C, не так ли? != равно ‹› в паскалях :) - person LU RD; 02.02.2012
comment
Мой основной язык разработки — C++, я мало работаю с Delphi, кроме написания компонентов. - person Remy Lebeau; 02.02.2012
comment
Большое спасибо РЛ. Ваше решение сработало! Мне пришлось изменить несколько деталей, и я бы устранил незначительные синтаксические различия. Я очень ценю тот факт, что вы можете переключаться между одним языком и другим. Хотел бы я освоить один язык, не говоря уже об использовании нескольких!! Еще раз спасибо. Тед - person Gizmo_the_Great; 03.02.2012