为什么我的程序集结构的大小与 GetOpenFileNameA 函数期望的结构大小不匹配?

1 assembly winapi struct masm calling-convention

我正在尝试使用 Win32 API 和 x64 程序集显示打开的文件对话框。为此,我将预期结构的内存分配与结构的内存分配OPENFILENAMEA(在commdlg.h)中进行匹配,但我似乎偏离了 4 个字节,因为我的结构的大小是 140 字节。如果我手动将参数设置为 136 或 152,该CommDlgExtendedError()函数不会返回(0x0001) ,而是会出现“访问冲突读取位置 0x0000010000007FF7”错误。CDERR_STRUCTSIZElStructSize

ml64.exe在 Visual Studio 2022 Community 中使用 MASM ( ) 并在 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;
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

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
Run Code Online (Sandbox Code Playgroud)

我尝试为结构设置参数,但这没有任何区别,因此我尝试通过将每个参数设置为 null(除了 和lStructSize结构lpstrFile参数)来获取最少量的代码来打开对话框。

Jes*_*ter 6

正如Peter 所评论的,C 结构体具有用于对齐的填充。您缺少 3 个双字,这使您的大小从预期的 140 变为 152。您必须在 后插入填充lStructSizenMaxFile并将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
Run Code Online (Sandbox Code Playgroud)

  • 附带说明一下,MASM [`struct`](https://learn.microsoft.com/en-us/cpp/assembler/masm/struct-masm?view=msvc-170) 关键字采用对齐参数。在这种情况下,这将是“tagOFNA STRUCT 8”(与使用“/Zp8”编译相同,除了后者将默认应用于所有结构)。 (3认同)