Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / ntdll NtQueryInformationFile x64 / 14 сообщений из 14, страница 1 из 1
24.06.2020, 19:20
    #39972891
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
Добрый день. Долгое время пользовался самописной 32-хбитной программой, которая вытаскивает параметры файлов с помощью функции NtQueryInformationFile. Решил переписать программу и в процессе модификации собрать ее как 64-хбитную. Обнаружилось, что в 64-хбитном режиме функция не работает - возвращает код 0x80000002. С 32-хбитным режимом никаких проблем - все прекрасно живет. Перерыл полгугла - нигде не описано каких-то различий между вызовами функции под x86 и x64. Все параметры и их типы теоретически должны быть идентичны. Что я упускаю? Никто не сталкивался с подобной ситуацией?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    OD: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

Uses
  UITypes;

{$R *.dfm}

Type
  IO_STATUS_BLOCK = Packed Record
                      NTSTATUS    : Pointer;
                      Information : DWord;
                    End;
  PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;

  FILE_BASIC_INFORMATION = Packed Record
                             CreationTime, LastAccessTime, LastWriteTime, ChangeTime : FileTime;
                             FileAttributes, Reserve                                 : ULong
                           End;
  PFILE_BASIC_INFORMATION = ^FILE_BASIC_INFORMATION;

Const
  FileBasicInformation = 4;
  STATUS_SUCCESS       = 0;

function NtQueryInformationFile(hFile : THandle; IoStatusBlock : PIO_STATUS_BLOCK; FileInformation : PFILE_BASIC_INFORMATION; Length : ULong; FileInformationClass : ULong) : ULong; StdCall; External 'ntdll' Name 'ZwQueryInformationFile';

function FileTimeToDateTime(FileTime : TFileTime) : TDateTime;

Var
  ModifiedTime : TFileTime;
  SystemTime   : TSystemTime;

begin
  Result   := 0;
  If (FileTime.dwLowDateTime = 0) And (FileTime.dwHighDateTime = 0) Then Exit;
  Try
    FileTimeToLocalFileTime(FileTime, ModifiedTime);
    FileTimeToSystemTime(ModifiedTime, SystemTime);
    Result := SystemTimeToDateTime(SystemTime)
  Except
    Result := Now
  End
end;

function GetFileDatesAndAttributes(Const AFileName : String; Var CrTime, LWTime, LATime, ChTime: TDateTime; Var FAttributes : Integer) : Boolean;

Var
  FHandle         : THandle;
  StatusBlock     : IO_STATUS_BLOCK;
  FileInformation : FILE_BASIC_INFORMATION;
  R               : ULong;

Begin
  Result          := False;
  FHandle         := CreateFile(Pchar(AFileName), GENERIC_READ, FILE_SHARE_READ, Nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  If FHandle = INVALID_HANDLE_VALUE Then Exit;
  Try
    R             := NtQueryInformationFile(FHandle, @StatusBlock, @FileInformation, SizeOf(FileInformation), FileBasicInformation);
    {If R = STATUS_SUCCESS Then} With FileInformation Do
    Begin
      CrTime      := FileTimeToDateTime(CreationTime);
      LATime      := FileTimeToDateTime(LastAccessTime);
      LWTime      := FileTimeToDateTime(LastWriteTime);
      ChTime      := FileTimeToDateTime(ChangeTime);
      FAttributes := FileAttributes;
      Result      := True
    End
  Finally
    CloseHandle(FHandle)
  End
End;

procedure TForm1.Button1Click(Sender: TObject);

Var
  D1, D2, D3, D4 : TDateTime;
  I              : Integer;

begin
  If Not OD.Execute Then Exit;
  If GetFileDatesAndAttributes(OD.FileName, D1, D2, D3, D4, I) Then
  Begin
    Edit1.Text := DateTimeToStr(D1);
    Edit2.Text := DateTimeToStr(D2);
    Edit3.Text := DateTimeToStr(D3);
    Edit4.Text := DateTimeToStr(D4);
  End
  Else MessageDlg('Error!', mtError, [mbOk], 0)
end;

end.
...
Рейтинг: 0 / 0
24.06.2020, 19:43
    #39972904
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
http://docwiki.embarcadero.com/Libraries/Rio/en/System.IOUtils.TFile

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
var
  FilePath: string;
  Attrs: TFileAttributes;
begin
  FilePath := 'c:\Users\desktop.ini';
  Edit1.Text := DateTimeToStr(TFile.GetCreationTime(FilePath));
  Edit2.Text := DateTimeToStr(TFile.GetLastAccessTime(FilePath));
  Edit3.Text := DateTimeToStr(TFile.GetLastWriteTime(FilePath));
  Attrs := TFile.GetAttributes(FilePath);
end;
...
Рейтинг: 0 / 0
24.06.2020, 19:46
    #39972906
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
X-Cite, если бы мне хватало только трех дат, я именно так бы и поступил. NtQueryInformationFile возвращает 4
...
Рейтинг: 0 / 0
24.06.2020, 23:06
    #39972939
Michael Longneck
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
Note If the call to this function occurs in user mode, you should use the name "NtQueryInformationFile" instead of "ZwQueryInformationFile".
...
Рейтинг: 0 / 0
24.06.2020, 23:20
    #39972941
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
Michael Longneck, и что? А я что в коде использовал?
...
Рейтинг: 0 / 0
24.06.2020, 23:27
    #39972943
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
0x80000002 = EXCEPTION_DATATYPE_MISALIGNMENT

У вас структуры неправильно объявлены.

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_status_block
...
Рейтинг: 0 / 0
24.06.2020, 23:32
    #39972945
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
GunSmoker, а как объяснить, что в 32-хбитном варианте никаких проблем со структурами не возникает?
...
Рейтинг: 0 / 0
25.06.2020, 01:11
    #39972964
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
S_Gur
GunSmoker, а как объяснить, что в 32-хбитном варианте никаких проблем со структурами не возникает?

Каким-то чудом, судя по всему.

Для начала:
Код: pascal
1.
2.
3.
4.
IO_STATUS_BLOCK = Packed Record
                      NTSTATUS    : Pointer;
                      Information : DWord;
                    End;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
typedef struct _IO_STATUS_BLOCK {
  union {
    NTSTATUS Status;
    PVOID    Pointer;
  } DUMMYUNIONNAME;
  ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

В x64, если что, ULONG_PTR - это не DWord.

Для продолжения :
Код: pascal
1.
2.
3.
4.
FILE_BASIC_INFORMATION = Packed Record
                             CreationTime, LastAccessTime, LastWriteTime, ChangeTime : FileTime;
                             FileAttributes, Reserve                                 : ULong
                           End;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
typedef struct _FILE_BASIC_INFORMATION {
  LARGE_INTEGER CreationTime;
  LARGE_INTEGER LastAccessTime;
  LARGE_INTEGER LastWriteTime;
  LARGE_INTEGER ChangeTime;
  ULONG         FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
...
Рейтинг: 0 / 0
25.06.2020, 06:06
    #39972972
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
alekcvp, судя по этой - http://delphiexpert.ru/tfiletime.html - статье, TFileTime - это и есть LARGE_INTEGER. Насколько я понимаю, FILE_BASIC_INFORMATION я описал вполне корректно
...
Рейтинг: 0 / 0
25.06.2020, 06:36
    #39972974
S_Gur
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
В результате изысканий в указанном знающими товарищами направлении, наткнулся на следующую статейку: https://coderoad.ru/3707252/Как-преобразовать-объединение-C-внутри-структуры-в-Delphi

В результате оформилась вполне себе рабочая структура:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
IO_STATUS_BLOCK = record
    case Integer of
      0: (
        Status: NTSTATUS;
        Pointer_: Pointer);
      1: (
        case Padding: DWORD of
          0: (
            Information: ULONG_PTR));
  end;



FILE_BASIC_INFORMATION оставлен без изменений - там все правильно

Функция заработала, всем спасибо. Тема закрыта
...
Рейтинг: 0 / 0
25.06.2020, 14:19
    #39973172
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
S_Gur
В результате оформилась вполне себе рабочая структура:
Сами поняли, что написали? А написан абсолютный сюр.

Для потомков оставлю правильные структуры
alekcvp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
typedef struct _IO_STATUS_BLOCK {
  union {
    NTSTATUS Status;
    PVOID    Pointer;
  } DUMMYUNIONNAME;
  ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
IO_STATUS_BLOCK = record
  Misc: record
    case Byte of
      0: (Status: NTSTATUS);
      1: (Pointer_: Pointer);
    end;
  Information: ULONG_PTR;
end;


alekcvp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
typedef struct _FILE_BASIC_INFORMATION {
  LARGE_INTEGER CreationTime;
  LARGE_INTEGER LastAccessTime;
  LARGE_INTEGER LastWriteTime;
  LARGE_INTEGER ChangeTime;
  ULONG         FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

Код: pascal
1.
2.
3.
4.
5.
6.
7.
FILE_BASIC_INFORMATION = record
  CreationTime: LARGE_INTEGER;
  LastAccessTime: LARGE_INTEGER;
  LastWriteTime: LARGE_INTEGER;
  ChangeTime: LARGE_INTEGER;
  FileAttributes: ULONG;
end;


Обратите внимание на отсутствие packed
...
Рейтинг: 0 / 0
25.06.2020, 16:04
    #39973219
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
S_Gur
GunSmoker, а как объяснить, что в 32-хбитном варианте никаких проблем со структурами не возникает?


Как известно, 90% кода в интернете - говно .
...
Рейтинг: 0 / 0
26.06.2020, 00:56
    #39973385
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
_Vasilisk_
Обратите внимание на отсутствие packed

Кстати, а typedef struct в х86 по-умолчанию какое выравнивание имеет?
S_Gur
alekcvp, судя по этой - http://delphiexpert.ru/tfiletime.html - статье, TFileTime - это и есть LARGE_INTEGER. Насколько я понимаю, FILE_BASIC_INFORMATION я описал вполне корректно

Где в исходной структуре вы увидели поле Reserve ?..
...
Рейтинг: 0 / 0
26.06.2020, 01:33
    #39973389
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ntdll NtQueryInformationFile x64
alekcvp
в х86 по-умолчанию какое выравнивание имеет?

8 вроде всегда было.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / ntdll NtQueryInformationFile x64 / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]