Почему размер моей структуры сборки не соответствует размеру структуры, ожидаемому функцией GetOpenFileNameA?

Я пытаюсь отобразить диалог открытия файла, используя Win32 API и сборку x64. Для этого я сопоставляю распределение памяти ожидаемой структуры с распределением памяти структуры OPENFILENAMEAcommdlg.h), но, похоже, я ошибаюсь на 4 байта, поскольку размер моей структуры составляет 140 байт. Функция CommDlgExtendedError() не возвращает CDERR_STRUCTSIZE (0x0001), если я вручную устанавливаю для параметра lStructSize значение 136 или 152, но вместо этого возникает ошибка «Нарушение доступа к местоположению чтения 0x0000010000007FF7».

Я использую MASM (ml64.exe) в Visual Studio 2022 Community и собираю под x64.

Вот структура, которую я пытаюсь сопоставить (lpEditInfo и lpstrPrompt опущены) из: https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea

typedef struct tagOFNA {
  DWORD         lStructSize;
  HWND          hwndOwner;
  HINSTANCE     hInstance;
  LPCSTR        lpstrFilter;
  LPSTR         lpstrCustomFilter;
  DWORD         nMaxCustFilter;
  DWORD         nFilterIndex;
  LPSTR         lpstrFile;
  DWORD         nMaxFile;
  LPSTR         lpstrFileTitle;
  DWORD         nMaxFileTitle;
  LPCSTR        lpstrInitialDir;
  LPCSTR        lpstrTitle;
  DWORD         Flags;
  WORD          nFileOffset;
  WORD          nFileExtension;
  LPCSTR        lpstrDefExt;
  LPARAM        lCustData;
  LPOFNHOOKPROC lpfnHook;
  LPCSTR        lpTemplateName;
  LPEDITMENU    lpEditInfo;
  LPCSTR        lpstrPrompt;
  void          *pvReserved;
  DWORD         dwReserved;
  DWORD         FlagsEx;
} OPENFILENAMEA, *LPOPENFILENAMEA;

Вот мой код:

extrn ExitProcess: PROC
extrn GetOpenFileNameA: PROC
extrn CommDlgExtendedError: PROC

.data
filename db 256 dup(0)
tagOFNA STRUCT
  lStructSize       dd 0    ; 0 - dword
  hwndOwner         dq 0    ; 4 - qword
  hInstance         dq 0    ; 12    - qword
  lpstrFilter       dq 0    ; 20    - qword
  lpstrCustomFilter dq 0    ; 28    - qword
  nMaxCustFilter    dd 0    ; 36    - dword
  nFilterIndex      dd 0    ; 40    - dword
  lpstrFile         dq offset filename  ; 44    - qword
  nMaxFile          dd 256  ; 52    - dword
  lpstrFileTitle    dq 0    ; 56    - qword
  nMaxFileTitle     dd 0    ; 64    - dword
  lpstrInitialDir   dq 0    ; 68    - qword
  lpstrTitle        dq 0    ; 76    - qword
  Flags             dd 0    ; 84    - dword
  nFileOffset       dw 0    ; 88    - word
  nFileExtension    dw 0    ; 90    - word
  lpstrDefExt       dq 0    ; 92    - qword
  lCustData         dq 0    ; 100   - qword
  lpfnHook          dq 0    ; 108   - qword
  lpTemplateName    dq 0    ; 116   - qword
  pvReserved        dq 0    ; 124   - qword
  dwReserved        dd 0    ; 132   - dword
  FlagsEx           dd 0    ; 136   - dword
tagOFNA ENDS

myofn tagOFNA <sizeof tagOFNA>

.code
main PROC
    sub rsp, 28h

    lea  rcx, myofn

    call GetOpenFileNameA

    call CommDlgExtendedError
    mov rcx, rax
    call ExitProcess
main ENDP
end

Я пытался установить параметры для структуры, но это не имело никакого значения, поэтому я попытался получить минимальный объем кода, чтобы просто открыть диалоговое окно, установив для каждого параметра значение null, кроме параметров структуры lStructSize и lpstrFile.

Было бы несколько необычно иметь смещенные qwords; Вы уверены, что после DWORD lStructSize; нет отступов, чтобы выровнять qword HWND и другие более поздние qwords, которые в вашем asm имеют нечетное число, кратное 8? (Или HWND по-прежнему 32-битный в x64?) Вы можете посмотреть сгенерированный компилятором asm, чтобы проверить смещения структур и увидеть, где смещения элементов отличаются от вашего asm. (godbolt.org). например напишите функции, которые назначают несколько членов. Вы можете выполнить «двоичный поиск», чтобы найти первый элемент с неправильным смещением.

Peter Cordes 06.08.2023 23:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как Питер прокомментировал, структура C имеет отступы для выравнивания. Вам не хватает 3 двойных слов, которые увеличивают размер от 140 до 152, как и ожидалось. Вы должны вставить дополнение после lStructSize, nMaxFile и nMaxFileTitle, чтобы выровнять следующие элементы qword с числом, кратным 8:

  lStructSize       dd 0    ; 0 - dword
  pad1              dd 0    ; 4 - dword
  hwndOwner         dq 0    ; 8 - qword
  hInstance         dq 0    ; 16    - qword
  lpstrFilter       dq 0    ; 24    - qword
  lpstrCustomFilter dq 0    ; 32    - qword
  nMaxCustFilter    dd 0    ; 40    - dword
  nFilterIndex      dd 0    ; 44    - dword
  lpstrFile         dq offset filename  ; 48    - qword
  nMaxFile          dd 256  ; 56    - dword
  pad2              dd 0    ; 60    - dword
  lpstrFileTitle    dq 0    ; 64    - qword
  nMaxFileTitle     dd 0    ; 72    - dword
  pad3              dd 0    ; 76    - dword
  lpstrInitialDir   dq 0    ; 80    - qword
  lpstrTitle        dq 0    ; 88    - qword
  Flags             dd 0    ; 96    - dword
  nFileOffset       dw 0    ; 100   - word
  nFileExtension    dw 0    ; 102   - word
  lpstrDefExt       dq 0    ; 104   - qword
  lCustData         dq 0    ; 112   - qword
  lpfnHook          dq 0    ; 120   - qword
  lpTemplateName    dq 0    ; 128   - qword
  pvReserved        dq 0    ; 136   - qword
  dwReserved        dd 0    ; 144   - dword
  FlagsEx           dd 0    ; 148   - dword

Кстати, ключевое слово MASM struct принимает параметр выравнивания. В этом случае это будет tagOFNA STRUCT 8 (то же самое, что компиляция с /Zp8, за исключением того, что последний будет применяться по умолчанию ко всем структурам).

Neitsa 07.08.2023 10:27

Другие вопросы по теме