我正在尝试使用 win32 api 和 x64 程序集打开一个打开的文件对话框。为此,我将预期结构的内存分配与 OPENFILENAMEA 结构 (commdlg.h) 的内存分配进行匹配,但我似乎偏离了 4 个字节,因为我的结构的大小是 140 个字节,但 CommDlgExtendedError 函数仅不这样做如果我手动将 lStructSize 参数设置为 136 或 152,则不会返回 CDERR_STRUCTSIZE (0x0001)。当我手动将其设置为 136 或 152 时,会发生访问冲突读取位置 0x0000010000007FF7 错误。 我在 Visual Studio 2022 Community 中使用 MASM (ml64.exe) 并在 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
我尝试过为结构设置参数,但这没有任何区别,所以我尝试通过将每个参数设置为空(lStructSize 和 lpstrFile 除外)来获取最少量的代码来打开一个打开的文件对话框结构体参数。
正如 Peter 评论的那样,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 ; 84 - qword
lpstrTitle dq 0 ; 92 - qword
Flags dd 0 ; 100 - dword
nFileOffset dw 0 ; 104 - word
nFileExtension dw 0 ; 106 - word
lpstrDefExt dq 0 ; 108 - 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