Я пытаюсь выполнить некоторую автоматизацию Office через 64-разрядную сборку, используя ml64.exe из Visual Studio 2019. Прежде чем я могу вызвать интерфейсы COM Office, мне нужно вызвать CoInitialize. В настоящее время я просто тестирую инициализацию COM и запись в консоль (обычно я не пишу ассемблерный код). Если я закомментирую строку
call CoInitialize
API-вызов WriteConsoleW работает как положено и выводит сообщение на экран " COM не удалось инициализировать "Однако, как только я добавляю вызов CoInitialize обратно, на экран консоли ничего не выводится, и cra sh либо.
; *************************************************************************
; 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