我正在尝试使用 Visual Studio 2019 中的 ml64.exe 通过 64 位程序集执行一些 Office 自动化。在调用 Office COM 接口之前,我需要调用 CoInitialize。我目前正在测试初始化 COM 并写入控制台(我通常不编写汇编代码)如果我注释掉行
call CoInitialize
WriteConsoleW api 调用按预期工作并向屏幕输出消息“COM 无法初始化”但是,一旦我将调用 CoInitialize 添加回来,控制台屏幕就没有任何输出,并且也会崩溃。
; *************************************************************************
; Proto types for API functions and structures
; *************************************************************************
EXTRN GetStdHandle:PROC
EXTRN WriteConsoleW:PROC
EXTRN CoCreateInstance:PROC
EXTRN CoInitialize:PROC
EXTRN SysFreeString:PROC
EXTRN SysStringByteLen:PROC
EXTRN SysAllocStringByteLen:PROC
EXTRN OleRun:PROC
EXTRN ExitProcess:PROC
.const
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12
; *************************************************************************
; Object libraries
; *************************************************************************
includelib user32.lib
includelib kernel32.lib
includelib ole32.lib
includelib oleaut32.lib
; *************************************************************************
; Our data section.
; *************************************************************************
.data
strErrComFailed dw 'C','O','M',' ','F','a','i','l','e','d',' ','t','o',' ','i','n','i','t','i','a','l','i','z','e',0,0
strErrOutlookFailed dw 'F','a','i','l','e','d',' ','t','o',' ','i','n','i','t','i','a','l','i','z','e',' ','O','u','t','l','o','o','k',0,0
; {0006F03A-0000-0000-C000-000000000046}
CLSID_OutlookApplication dd 0006f03ah
dw 0000h
dw 0000h
dw 0C000h
db 00h
db 00h
db 00h
db 00h
db 00h
db 46h
; {00063001-0000-0000-C000-000000000046}
IID_OutlookApplication dd 00063001h
dw 0000h
dw 0000h
dw 0C000h
db 00h
db 00h
db 00h
db 00h
db 00h
db 46h
; {00000000-0000-0000-C000-000000000046}
IID_IUnknown dd 00000000h
dw 0000h
dw 0000h
dw 0C000h
db 00h
db 00h
db 00h
db 00h
db 00h
db 46h
; *************************************************************************
; Our executable assembly code starts here in the .code section
; *************************************************************************
.code
wcslen PROC inputString:QWORD
LOCAL stringLength:QWORD
mov QWORD PTR inputString, rcx
mov QWORD PTR stringLength, 0h
continue:
mov rax, QWORD PTR inputString
mov rcx, QWORD PTR stringLength
movzx eax, word ptr [rax+rcx*2]
test eax, eax
je finished
mov rax, QWORD PTR stringLength
inc rax
mov QWORD PTR stringLength, rax
jmp continue
finished:
mov rax, QWORD PTR stringLength
ret
wcslen ENDP
main PROC
LOCAL hStdOutput:QWORD
LOCAL hErrOutput:QWORD
LOCAL hResult:DWORD
xor ecx,ecx
call CoInitialize
mov DWORD PTR hResult, eax
mov ecx, STD_OUTPUT_HANDLE
call GetStdHandle
mov QWORD PTR hStdOutput, rax
mov ecx, STD_ERROR_HANDLE
call GetStdHandle
mov QWORD PTR hErrOutput, rax
lea rcx,strErrComFailed
call wcslen
mov QWORD PTR [rsp+32], 0
xor r9d, r9d ; lpNumberOfCharsWritten
mov r8d, eax ; nNumberOfCharsToWrite
lea rdx,QWORD PTR strErrComFailed
mov rcx,QWORD PTR hStdOutput
call WriteConsoleW
; When the message box has been closed, exit the app with exit code eax
mov ecx, eax
call ExitProcess
ret
main ENDP
End
在调用 CoInitialize 之前,WinDbg 显示以下寄存器状态:
00007ff7`563e1041 e865000000 call Win64App+0x10ab (00007ff7`563e10ab)
0:000> r
rax=00007ff7563e1037 rbx=0000000000000000 rcx=0000000000000000
rdx=00007ff7563e1037 rsi=0000000000000000 rdi=0000000000000000
rip=00007ff7563e1041 rsp=000000a905affa58 rbp=000000a905affa70
r8=000000a9058d6000 r9=00007ff7563e1037 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
Win64App+0x1041:
00007ff7`563e1041 e865000000 call Win64App+0x10ab (00007ff7`563e10ab)
0:000> r ecx
ecx=0
在调用 CoInitialize 之后,有以下寄存器状态:
0:000> r
rax=0000000000000000 rbx=0000000000000000 rcx=8aa77f80a0990000
rdx=0000000000000015 rsi=0000000000000000 rdi=0000000000000000
rip=00007ff7563e1046 rsp=000000a905affa58 rbp=000000a905affa70
r8=0000029af97e2620 r9=0000029af97e1440 r10=0000000000000005
r11=000000a905aff9d8 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
Win64App+0x1046:
00007ff7`563e1046 8945ec mov dword ptr [rbp-14h],eax ss:000000a9`05affa5c=00000000
0:000> r eax
eax=0
调用 GetStdHandle 后:
0:000> r
rax=0000000000000074 rbx=0000000000000000 rcx=0000029af97d2840
rdx=0000000000000015 rsi=0000000000000000 rdi=0000000000000000
rip=00007ff7563e1053 rsp=000000a905affa58 rbp=000000a905affa70
r8=0000029af97e2620 r9=0000029af97e1440 r10=0000000000000005
r11=000000a905aff9d8 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
在调用 WriteConsoleW 时,参数似乎仍然正确,但没有输出到屏幕:
KERNEL32!WriteConsoleW:
00007ffb`a97028f0 ff258a4c0500 jmp qword ptr [KERNEL32!_imp_WriteConsoleW (00007ffb`a9757580)] ds:00007ffb`a9757580={KERNELBASE!WriteConsoleW (00007ffb`a697b750)}
0:000> du rdx
00007ff7`563e3000 "COM Failed to initialize"
0:000> r
rax=0000000000000018 rbx=0000000000000000 rcx=0000000000000074
rdx=00007ff7563e3000 rsi=0000000000000000 rdi=0000000000000000
rip=00007ffba97028f0 rsp=000000a905affa50 rbp=000000a905affa70
r8=0000000000000018 r9=0000000000000000 r10=0000000000000005
r11=000000a905aff9d8 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
KERNEL32!WriteConsoleW:
00007ffb`a97028f0 ff258a4c0500 jmp qword ptr [KERNEL32!_imp_WriteConsoleW (00007ffb`a9757580)] ds:00007ffb`a9757580={KERNELBASE!WriteConsoleW (00007ffb`a697b750)}
我尝试改用 CoInitializeEx 并遇到同样的问题:
mov edx, COINIT_APARTMENTTHREADED ; dwCoInit (COINIT_APARTMENTTHREADED = 2)
xor ecx, ecx ; pvReserved
call CoInitializeEx