我必须调用WinApi SHFileOperationW函数,但在此之前,我需要填充此结构
typedef struct _SHFILEOPSTRUCTW {
HWND hwnd;
UINT wFunc;
PCZZWSTR pFrom;
PCZZWSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
PCWSTR lpszProgressTitle;
} SHFILEOPSTRUCTW, *LPSHFILEOPSTRUCTW;
在MASM中,我这样定义:
SHFILEOPSTRUCT struct
hwnd dq ?
wFunc dd ?
pFrom dq ?
pTo dq ?
fFlags dw ?
fAnyOperationsAborted dd ?
hNameMappings dq ?
lpszProgressTitle dq ?
SHFILEOPSTRUCT ends
在.data部分,我初始化我的结构:
fos SHFILEOPSTRUCT <?>
因此,当我用mov操作填充结构并在rcx(函数的1个arg(中加载地址时,会导致错误,但如果我在堆栈中推送结构字段并传递给函数RSP,它的工作就很好。为什么会这样?即使是0,我也需要填写所有字段吗?(不起作用↓)
mov [fos.hwnd], 0 ; hWnd
mov [fos.wFunc], FO_DELETE ; Delete
mov rax, offset filename
mov [fos.pFrom], rax ; Filename
mov [fos.fFlags], FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT
lea rcx, fos
vs(这是工作↓)
push 0
push 0
push 0
push FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT
push 0
pushaddr filename
push FO_DELETE
push 0
mov rcx, rsp
然后我在堆栈中分配一些空间,并调用函数:
sub rsp, 28h
call SHFileOperationW
Windows SDK中的C/C++头采用平台的默认值使用对齐
这由msvc和ML/ML64中的/Zp(结构成员对齐(选项控制(对齐可以是1、2、4、8或16(
另请参阅align如何与数据打包配合使用
MSVC和ML64之间的区别:MSVC使用/Zp16作为x64和ARM64的默认值,但ML64不使用。
因此您需要或在ML64命令行中直接设置/Zp16(最好(或在STRUCT
声明中直接设置对齐:
如SHFILEOPSTRUCTW struct 16
还声明变量In。数据部分-意味着使用全局变量和坏的解决方案。这必须是局部变量,所以在堆栈中也是如此。代码可以看起来像
.code
SHFILEOPSTRUCTW struct 16
hwnd dq ?
wFunc dd ?
pFrom dq ?
pTo dq ?
fFlags dw ?
fAnyOperationsAborted dd ?
hNameMappings dq ?
lpszProgressTitle dq ?
SHFILEOPSTRUCTW ends
FO_DELETE EQU 03h
FOF_NOCONFIRMATION EQU 10h
FOF_ALLOWUNDO EQU 40h
FOF_SILENT EQU 04h
EXTERN __imp_SHFileOperationW:QWORD
VarSize EQU ((SIZEOF SHFILEOPSTRUCTW + 15) and not 15)
fos EQU [rsp + 20h]
er_ff proc
sub rsp, 28h + VarSize
xor eax,eax
mov fos[SHFILEOPSTRUCTW.hwnd],rax
mov fos[SHFILEOPSTRUCTW.wFunc],FO_DELETE
mov fos[SHFILEOPSTRUCTW.pFrom],rcx
mov fos[SHFILEOPSTRUCTW.pTo],rax
mov fos[SHFILEOPSTRUCTW.fFlags],FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT
lea rcx,fos
call __imp_SHFileOperationW
add rsp, 28h + VarSize
ret
er_ff endp
end
因此使用CCD_ 3更好地ml64/c/Cp/Zp16"$(InputFileName(">