COM в Ассемблере - Программа-пример с использованием COM
ОГЛАВЛЕНИЕ
Программа-пример с использованием COM
Вот исходник, который написан так, чтобы быть максимально совместимым с любым ассемблером, который вы предпочтете (по крайней мере, чтобы вам не пришлось делать глобальных изменений).
Эта программа использует интерфейсы Windows Shell, чтобы отобразить содержиом Рабочего стола. Программа не закончена, но она показывает, как инициализровать библиотеку COM, деинициализировать и использовать. Я также покажу, как использовать shell-библиотека, чтобы получить папки и объекты, и выполнять над ними различные действия
.386
.model flat, stdcall
include windows.inc ; подключает стандартных заголовочный файл
include shlobj.inc ; этот заголовочный файл содержит константы и
; определения shell'а
;----------------------------------------------------------
.data
wMsg MSG <?>
g_hInstance dd ?
g_pShellMalloc dd ?
pshf dd ? ; объект папки shell'а
peidl dd ? ; объект списка id
lvi LV_ITEM <?>
iCount dd ?
strret STRRET <?gt;
shfi SHFILEINFO <?>
...
;----------------------------------------------------------
.code
; Entry Point
start:
push 0h
call GetModuleHandle
mov g_hInstance,eax
call InitCommonControls
; Инициализируем библиотеку Component Object Model (COM)
push 0
call CoInitialize
test eax,eax ; ошибка, если MSB = 1
; (MSB = бит знака)
js exit ; js = переход, если установлен бит знака
; Получаем указатель на объект shell'а IMalloc и сохраняем его в глобальную
; переменную
push offset g_pShellMalloc
call SHGetMalloc
cmp eax, E_FAIL
jz shutdown
; Здесь мы должны создать окна, list view, цикл обработки сообщений и так
; далее...
; ....
; Очищение
; Освобождаем указатель на объект IMalloc
mov eax, g_pShellMalloc
push eax
mov eax, [eax]
call [eax + Release] ; g_pShellMalloc->Release();
shutdown:
; закрываем библиотеку COM
call CoUninitialize
exit:
push wMsg.wParam
call ExitProcess
; Здесь программа прекращает свое выполнение
;----------------------------------------------------------
FillListView proc
; получаем папку Рабочего стола, сохраняем в pshf
push offset pshf
call SHGetDesktopFolder
; получаем объекты в папке Рабочего стола, используя метода EnumObjects
; объекта папки Рабочего стола
push offset peidl
push SHCONTF_NONFOLDERS
push 0
mov eax, pshf
push eax
mov eax, [eax]
call [eax + EnumObjects]
xor ebx, ebx ; используем ebx в качестве счетчика
; перебираем элементы списка id
idlist_loop:
; Получаем следующий элемент списка
push 0
push offset pidl
push 1
mov eax, peidl
push eax
mov eax, [eax]
call [eax + Next]
test eax,eax
jnz idlist_endloop
mov lvi.imask, LVIF_TEXT or LVIF_IMAGE
mov lvi.iItem, ebx
; Получаем имя элемента, используя метод GetDisplayNameOf
push offset strret
push SHGDN_NORMAL
push offset pidl
mov eax, pshf
push eax
mov eax, [eax]
call [eax + GetDisplayNameOf]
; GetDisplayNameOf возвращает имя в одной из трех форм, поэтому выберите
; правильную форму и поступайте соответствующе
cmp strret.uType, STRRET_CSTR
je strret_cstr
cmp strret.uType, STRRET_OFFSET
je strret_offset
strret_olestr:
; здесь вы можете использовать WideCharToMultiByte, чтобы получить
; строку, я оставляю это на вас, так как я ленив
jmp strret_end
strret_cstr:
lea eax, strret.cStr
jmp strret_end
strret_offset:
mov eax, pidl
add eax, strret.uOffset
strret_end:
mov lvi.pszText, eax
; Получаем иконки элементов
push SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON or
SHGFI_ICON
push sizeof SHFILEINFO
push offset shfi
push 0
push pidl
call SHGetFileInfo
mov eax, shfi.iIcon
mov lvi.iImage, eax
; теперь добавляем элементы в список
push offset lvi
push 0
push LVM_INSERTITEM
push hWndListView
call SendMessage
; увеличиваем значение счетчика ebx и делаем еще один повтор цикла
inc ebx, ebx
jmp idlist_loop
idlist_endloop:
; теперь освобождаем список id
; Помните, что все зарезервированные объекты должны быть освобождены
mov eax, peidl
push eax
mov eax,[eax]
call [eax + Release]
; освобождаем объект папки Рабочего стола
mov eax, pshf
push eax
mov eax,[eax]
call [eax + Release]
ret
FillListView endp
END start
Заключение
Хорошо, вот и все об использовании COM при программировании на ассемблере. Вероятно, что моя следующая статья расскажет о том, как определить собственные интерфейсы. Как вы можете видеть, использование COM вовсе не сложно, и с его помощью вы можете добавить очень мощные возможности в вашу программу, написанную на ассемблере.