powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / ntdll NtQueryInformationFile x64
14 сообщений из 14, страница 1 из 1
ntdll NtQueryInformationFile x64
    #39972891
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день. Долгое время пользовался самописной 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
ntdll NtQueryInformationFile x64
    #39972904
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
ntdll NtQueryInformationFile x64
    #39972906
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite, если бы мне хватало только трех дат, я именно так бы и поступил. NtQueryInformationFile возвращает 4
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972939
Michael Longneck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Note If the call to this function occurs in user mode, you should use the name "NtQueryInformationFile" instead of "ZwQueryInformationFile".
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972941
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Michael Longneck, и что? А я что в коде использовал?
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972943
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0x80000002 = EXCEPTION_DATATYPE_MISALIGNMENT

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

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_status_block
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972945
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmoker, а как объяснить, что в 32-хбитном варианте никаких проблем со структурами не возникает?
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972964
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
ntdll NtQueryInformationFile x64
    #39972972
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp, судя по этой - http://delphiexpert.ru/tfiletime.html - статье, TFileTime - это и есть LARGE_INTEGER. Насколько я понимаю, FILE_BASIC_INFORMATION я описал вполне корректно
...
Рейтинг: 0 / 0
ntdll NtQueryInformationFile x64
    #39972974
S_Gur
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В результате изысканий в указанном знающими товарищами направлении, наткнулся на следующую статейку: 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
ntdll NtQueryInformationFile x64
    #39973172
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
ntdll NtQueryInformationFile x64
    #39973219
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
S_Gur
GunSmoker, а как объяснить, что в 32-хбитном варианте никаких проблем со структурами не возникает?


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

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

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

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


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