Эта статья основана на коде Томаша Грыштара (Tomasz Grysztar) [Ссылка на исходники] и написана исключительно в образовательных целях. Она объясняет работу ассемблерного кода, который создает снимки экрана в формате JPEG.
Описание структур и API-функции преимущественно является переводом описаний с MSDN.
section '.rdata' data readable
; импортируемые функции и библиотеки
data import
library \
kernel32, 'KERNEL32.DLL', \
user32, 'USER32.DLL', \
gdi32, 'GDI32.DLL', \
gdiplus, 'GDIPLUS.DLL'
import gdiplus, \
GdiplusStartup, 'GdiplusStartup', \
GdiplusShutdown, 'GdiplusShutdown', \
GdipGetImageEncodersSize, 'GdipGetImageEncodersSize', \
GdipGetImageEncoders, 'GdipGetImageEncoders', \
GdipSaveImageToFile, 'GdipSaveImageToFile', \
GdipDisposeImage, 'GdipDisposeImage', \
GdipCreateBitmapFromHBITMAP, 'GdipCreateBitmapFromHBITMAP'
include 'api/kernel32.inc'
include 'api/user32.inc'
include 'api/gdi32.inc'
end data
Программа представлена двумя структурами:
Структура, содержащая блок аргументов, требуемых для функции GdiplusStartup.
Синтаксис:
typedef struct GdiplusStartupInput {
UINT32 GdiplusVersion;
DebugEventProc DebugEventCallback;
BOOL SuppressBackgroundThread;
BOOL SuppressExternalCodecs;
};
Объявление структуры в FASM:
struct GdiplusStartupInput
GdiplusVersion dd ?
DebugEventCallback dd ?
SuppressBackgroundThread dd ?
SuppressExternalCodecs dd ?
ends
Члены структуры представлены в таблице ниже:
Название | Тип | Описание |
---|---|---|
GdiplusVersion | UINT32 | Указывает версию GDI+. Должна быть 1. |
DebugEventCallback | DebugEventProc | Указатель на функцию обратного вызова, которую GDI+ может вызывать. Значение по умолчанию - NULL. |
SuppressBackgroundThread | BOOL | Логическое значение, указывающее, следует ли подавлять фоновый поток GDI+ |
SuppressExternalCodecs | BOOL | Логическое значение, указывающее, необходимо ли, чтобы GDI+ подавлял внешние кодеки изображений. |
Структура GdiplusStartupInput предоставляет конструктор, который устаналивает член структуры GdiplusVersion в 1 и позволяет указать значения для остальных трех членов. Все параметры конструктора являются необязательными, поэтому можно объявить перменную типа GdiplusStartupInput без передачи каких-либо аргументов конструктору, и все члены будут инициализированы соответствующими значениями по умолчанию.
Структура ImageCodecInfo предоставляет информацию об установленных кодеках изображения.
Синтаксис:
typedef struct ImageCodecInfo {
CLSID ClassID;
GUID FormatID;
WCHAR * CodecName;
WCHAR * DllName;
WCHAR * FormatDescription;
WCHAR * FilenameExtension;
WCHAR * MimeType;
DWORD Flags;
DWORD Version;
DWORD SigCount;
DWORD SigSize;
BYTE * SigPattern;
BYTE * SigMask;
};
Объявление структуры в FASM:
struct ImageCodecInfo
Clsid db 16 dup ?
FormatID db 16 dup ?
CodecName dd ?
DllName dd ?
FormatDescription dd ?
FilenameExtension dd ?
MimeType dd ?
Flags dd ?
Version dd ?
SigCount dd ?
SizeSize dd ?
SigPattern dd ?
SigMask dd ?
ends
Члены структуры представлены в таблице ниже:
Название | Тип | Описание |
---|---|---|
Clsid | CLSID | Идентификатор кодека |
FormatID | GUID | Идентификатор формата файла |
CodecName | WCHAR | Указатель строку, содержащую имя кодека. |
DllName | WCHAR | Указатель на строку, содержащую имя пути к DLL, в котором находится кодек |
FormatDescription | WCHAR | Указатель на строку, которая содержит имя формата файла, используемого кодеком |
FilenameExtension | WCHAR | Указатель на строку, которая содержит все расширения имен файлов, связанные с кодеком |
MimeType | WCHAR | Указатель на строку, которая содержит тип mime-кодека. |
Flags | DWORD | Комбинация флагов из перечисления ImageCodecFlags |
Version | DWORD | Целое число, указывающее версию кодека |
SigCount | DWORD | Целое число, которое указывает количество подписей, используемых файловым форматом, связанным с кодеком |
SizeSize | DWORD | Целое число, указывающее количество байтов в каждой подписи |
SigPattern | BYTE | Указатель на массив байтов, содержащий шаблон для каждой подписи |
SigMask | BYTE | Указатель на массив байтов, содержащий маску для каждой подписи |
API-функции, использованные в программе:
- GdiplusStartup
- GdipGetImageEncodersSize
- VirtualAlloc
- GetImageEncoders
- VirtualFree
- GetDC
- GetSystemMetrics
- CreateCompatibleBitmap
- CreateCompatibleDC
- SelectObject
- BitBlt
- GdipCreateBitmapFromHBITMAP
- GdipSaveImageToFile
- GdipDisposeImage
- DeleteObject
- ReleaseDC
- GdiplusShutdown
- ExitProcess
Функция GdiplusStartup инициализирует Windows GDI+.
Status GdiplusStartup(
__out ULONG_PTR token *token,
__in const GdiplusStartupInput *input,
__out GdiplusStartupOutput *output
);
Аргументы функции GdiplusStartup:
Название | Тип | Описание |
---|---|---|
token [out] | ULONG_PTR token* | Указатель на ULONG_PTR, который получает токен |
input [in] | const | GdiPlusStartupInput* |
output [out] | GdiplusStartupOutput* | Указатель на структуру GdiplusStartupOutput |
Использование в коде:
invoke GdiplusStartup, token, input, NULL
test eax, eax
jnz exit
Функция GdipGetImageEncodersSize получает число доступных кодировщиков изображения и размер массива объектов типа ImageCodecInfo, который возвращает функция GetImageEncoders.
Синтаксис:
Status GetImageEncodersSize(
__out UINT *numEncoders,
__out UINT *size
);
Аргументы функции GdipGetImageEncodersSize:
Название | Тип | Описание |
---|---|---|
numEncoders [out] | UINT* | Указатель на UINT, который получает число доступных кодировщиков изображения |
size [out] | UINT* | Указатель на UINT, который получает размер массива объектов ImageCodecInfo (в байтах), возвращаемых функцией GetImageEncoders |
Использование в коде:
invoke GdipGetImageEncodersSize, encoders_count, encoders_size
test eax, eax
jnz gdiplus_shutdown
С помощью данной функции есть возможность выделить или зарезервировать страницы виртуальной памяти. Между выделением и резервированием есть разница. При выделении физически выделяется память и естественно увеличивается файл подкачки. При резервировании этого не происходит.
Синтаксис:
LPVOID WINAPI VirtualAlloc(
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
Аргументы функции VirtualAlloc:
Название | Тип | Описание |
---|---|---|
lpAddress [in, optional] | LPVOID | Базовый адрес |
size [out] | SIZE_T | Размер области в байтах |
flAllocationType [in] | DWORD | Способ получения |
flProtect [in] | DWORD | Тип доступа |
Способ получения:
Название | Описание |
---|---|
MEM_COMMIT | Выполняется выделение страниц памяти для непосредственной работы с ними. Выделенные страницы заполняются нулями. |
MEM_RESERVE | Резервирует страницы памяти |
Тип доступа:
Название | Описание |
---|---|
PAGE_READONLY | Только чтение |
PAGE_READWRITE | Чтение и запись |
PAGE_EXECUTE | Только исполнение программного кода |
PAGE_EXECUTE_READ | Исполнение и чтение |
PAGE_EXECUTE_READWRITE | Исполнение, чтение и запись |
PAGE_GUARD | Сигнализация доступа к странице |
PAGE_NOACCESS | Запрещен любой вид доступа |
PAGE_NOCACHE | Отмена кэширования для страницы памяти |
Использование в коде:
invoke VirtualAlloc, 0, [encoders_size], MEM_COMMIT, PAGE_READWRITE
test eax, eax
jz gdiplus_shutdown
mov ebx, eax
Функция GetImageEncoders получает массив объектов типа ImageCodecInfo, которые содержат информацию о доступных кодировщиках изображений.
Синтаксис:
Status GetImageEncoders(
__in UINT numEncoders,
__in UINT size,
__out ImageCodecInfo *encoders
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
numEncoders [in] | UINT | Целое число, определяющее количество доступных кодировщиков изображений |
size [in] | UINT | Целое число, которое задает размер в байтах массив объектов типа ImageCodecInfo |
encoders [out] | ImageCodecInfo* | Указатель на буфер, который получает массив объектов типа ImageCodecInfo |
Использование в коде:
invoke GdipGetImageEncoders, [encoders_count], [encoders_size], ebx
test eax, eax
jnz gdiplus_shutdown
Функция VirtualFree освобождает выделенную память.
Синтаксис:
BOOL VirtualFree
(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
lpAddress | LPVOID | Базовый адрес |
dwSize | SIZE_T | Размер, если мы будем использовать тип освобождения, как MEM_RELEASE, то размер должен быть установлен в 0. |
encoders [out] | DWORD | Определяет, какая операция произойдет с памятью |
Типы операций с памятью:
Название | Описание |
---|---|
lpAddress | LPVOID |
MEM_RELEASE | Высвобождение используемой памяти |
MEM_DECOMMIT | Высвобождение зарезервированной памяти |
Использование в коде:
invoke VirtualFree, ebx, 0, MEM_RELEASE
Функция GetDC идентифицирует контекст устройства для CWnd клиентской области если успешно иначе, возвращаемое значение NULL.
Синтаксис:
HDC GetDC(
_In_ HWND hWnd
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hWnd | HWND | Дескриптор окна, чей контекст устройства должен быть извлечен |
Использование в коде:
invoke GetDC, HWND_DESKTOP
test eax, eax
jz gdiplus_shutdown
mov esi, eax
Функция GetSystemMetrics идентифицирует заданный системный показатель или настройку конфигурации системы.
Синтаксис:
int WINAPI GetSystemMetrics(
_In_ int nIndex
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
nIndex | int | Идентификатор настройки |
Использование в коде:
invoke GetSystemMetrics, SM_CYSCREEN
mov [screen_height], eax
invoke GetSystemMetrics,SM_CXSCREEN
mov [screen_width], eax
Функция CreateCompatibleBitmap создает точечный рисунок, совместимый с контекстом устройства.
Синтаксис:
HBITMAP CreateCompatibleBitmap(
_In_ HDC hdc,
_In_ int nWidth,
_In_ int nHeight
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hdc [in] | HDC | Дескриптор контекста устройства |
nWidth [in] | int | Ширина рисунка в пикселях |
nHeight [in] | int | Высота рисунка в пикселях |
Использование в коде:
invoke CreateCompatibleBitmap, esi, [screen_width], [screen_height]
test eax, eax
jz release_desktop_dc
mov ebx, eax
Функция CreateCompatibleDC создает контекст устройства памяти, который является совместимым с устройством, определенным pDC.
Синтаксис:
HDC CreateCompatibleDC(
_In_ HDC hdc
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hdc [in] | HDC | Указатель на контекст устройства |
Использование в коде:
invoke CreateCompatibleDC, esi
test eax, eax
jz delete_bitmap
mov edi, eax
Функция SelectObject выбирает объект в указанном контексте устройства. Новый объект заменяет предыдущий объект того же типа.
Синтаксис:
HGDIOBJ SelectObject(
_In_ HDC hdc,
_In_ HGDIOBJ hgdiobj
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hdc [in] | HDC | Указатель на контекст устройства |
hgdiobj [in] | HGDIOBJ | Указатель на объект, который должен быть выбран |
Использование в коде:
invoke SelectObject, edi, ebx
test eax, eax
jz delete_dc
Функция BitBlt копирует точечный рисунок от исходного контекста устройства до этого текущего контекста устройства.
Синтаксис:
BOOL BitBlt(
_In_ HDC hdcDest,
_In_ int nXDest,
_In_ int nYDest,
_In_ int nWidth,
_In_ int nHeight,
_In_ HDC hdcSrc,
_In_ int nXSrc,
_In_ int nYSrc,
_In_ DWORD dwRop
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hdcDest [in] | HDC | Указатель на контекст конечного устройства |
nXDest [in] | int | Определяет логическую x-координату левого верхнего угла прямоугольника адресата. |
nYDest [in] | int | Определяет логическую y-координату левого верхнего угла прямоугольника адресата. |
nWidth [in] | int | Определяет ширину (в логических модулях) прямоугольника адресата и исходного точечного рисунка. |
nHeight [in] | int | Определяет высоту (в логических модулях) прямоугольника адресата и исходного точечного рисунка. |
hdcSrc [in] | HDC | Указатель на объект HDC, который идентифицирует контекст устройства из которого точечный рисунок будет скопирован |
nXSrc [in] | int | Определяет логическую x-координату левого верхнего угла исходного точечного рисунка |
nYSrc [in] | int | Определяет логическую y-координату левого верхнего угла исходного точечного рисунка |
dwRop [in] | DWORD | Определяет растровую операцию, которую нужно выполнить |
Использование в коде:
invoke BitBlt, edi, 0, 0, [screen_width], [screen_height], esi, 0, 0, SRCCOPY
test eax, eax
jz delete_dc
Функция GdipCreateBitmapFromHBITMAP создает точечное изображение на основе дескриптора GDI и дескриптора палитры GDI.
Синтаксис:
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(
HBITMAP hbm,
HPALETTE hpal,
GpBitmap** bitmap
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hbm [in] | HBITMAP | Дескриптор точечного изображения |
hgdiobj [in] | HPALETTE | Дескриптор палитры GDI |
bitmap [out] | GpBitmap | Указатель на переменную DWORD, которая получает указатель на объект bitmap |
Использование в коде:
invoke GdipCreateBitmapFromHBITMAP, ebx, NULL, gdip_bitmap
test eax, eax
jnz delete_dc
Функция GdipSaveImageToFile сохраняет изображение в файл.
Синтаксис:
GpStatus WINGDIPAPI GdipSaveImageToFile(
GpImage *image,
GDIPCONST WCHAR* filename,
GDIPCONST CLSID* clsidEncoder,
GDIPCONST EncoderParameters* encoderParams
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
image [in] | GpImage | Указатель на изображение |
filename [in] | GDIPCONST | Указатель на строку unicode, которая указывает имя пути для сохраненного изображения |
clsidEncoder [in] | GDIPCONST | Указатель на CLSID, который указывает кодировщик, который будет использоваться для сохранения изображения |
encoderParams [in] | GDIPCONST | Указатель на структуру EncoderParameters, которая содержит параметры, используемые кодировщиком |
Использование в коде:
invoke GdipSaveImageToFile, [gdip_bitmap], file_name, encoder_clsid, NULL
Функция GdipDisposeImage удаляет указанное изображение.
Синтаксис:
GpStatus WINGDIPAPI GdipDisposeImage(
GpImage *image
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
image [in] | GpImage | Указатель на изображение |
Использование в коде:
invoke GdipDisposeImage, [gdip_bitmap]
Функция DeleteObject удаляет перо, кисть, шрифт, растровое изображение, область или палитру, освобождая все системные ресурсы, связанные с объектом. После удаления объекта указанный дескриптор более недействителен.
Синтаксис:
BOOL DeleteObject(
_In_ HGDIOBJ hObject
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hObject [in] | HGDIOBJ | Дескриптор объекта |
Использование в коде:
invoke DeleteObject, edi
Функция ReleaseDC освобождает контекст устройства (DC) для его использования другими приложениями.
Синтаксис:
int ReleaseDC(
_In_ HWND hWnd,
_In_ HDC hDC
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
hWnd [in] | HWND | Дескриптор окна, чей контекст должен быть высвобожден |
hDC [in] | HDC | Дескриптор контекста устройства, который надо высвободить |
Использование в коде:
invoke ReleaseDC, HWND_DESKTOP, esi
Функция GdiplusShutdown очищает ресурсы, используемые Windows GDI+.
Синтаксис:
void GdiplusShutdown(
__in ULONG_PTR token
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
token [in] | ULONG_PTR | Токен, возвращенный предыдущим вызовом GdiplusStartup |
Использование в коде:
invoke GdiplusShutdown, [token]
Функция ExitProcess заканчивает работу процесса и всех его потоков.
Синтаксис:
VOID ExitProcess(
UINT uExitCode
);
Аргументы функции:
Название | Тип | Описание |
---|---|---|
uExitCode [in] | UINT | Определяет код выхода для процесса, и для всех потоков, которые завершают работу в результате вызова этой функци |
Использование в коде:
invoke ExitProcess, 0