📄 iconworks.asm
字号:
; ----------------------------------------
;
; (C) Alex Demchenko (coban2k@mail.ru)
; http://www.cobans.net
;
; ----------------------------------------
; #########################################################################
.const
MAX_ICONS equ 256
VirtOffset equ 2000h
CXICON equ 16
CYICON equ 16
.data?
lpSection dd ?
SectionLen dd ?
SectionOff dd ?
xTable db (MAX_ICONS+1)*4 dup(?)
xTableOffset dd ?
hSuitableIcon dd ?
.code
; #########################################################################
; Add resource section to exe file
AddSection proc uses edi dwLen: DWORD
LOCAL lpName[9]: BYTE
mov edx, lpStubMem
mov edi, [edx+3Ch]
lea edi, [edx+edi] ; EDI points to PE header
; ImageSize
mov dword ptr[edi+50h], VirtOffset
mov eax, dwLen
add dword ptr[edi+50h], eax
; Resource table RVA & table size
.IF lpIconBuf != 0
mov dword ptr[edi+88h], VirtOffset
mov dword ptr[edi+8Ch], eax
.ENDIF
movzx eax, word ptr[edi+06h] ; Num of Objects
inc word ptr[edi+06h]
add edi, 0F8h ; Size of PE header
cdq
mov ecx, 28h
mul ecx
add edi, eax
mov dword ptr[edi], 'rsr.'
mov byte ptr[edi+4], 'c'
; Virtual size
push dwLen
pop dword ptr[edi+8]
; RVA
mov dword ptr[edi+0Ch], VirtOffset
; Physical size
push dwLen
pop dword ptr[edi+10h]
; Physical offset
push StubLen
pop dword ptr[edi+14h]
; Flags
mov dword ptr[edi+24h], 0C0000040h
ret
AddSection endp
; Convert mem addr to offset
ConvProc proc
mov eax, SectionOff
sub eax, lpSection
ret
ConvProc endp
; Add item to xTable
xTableAdd proc uses edi esi Off: DWORD
mov edi, offset xTable
mov esi, xTableOffset
push Off
pop dword ptr[edi+esi*4]
inc xTableOffset
ret
xTableAdd endp
; Write Resource Directory layer
WriteResDirectory proc N: DWORD
mov eax, SectionOff
xor edx, edx
mov [eax], edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
push N
pop dword ptr[eax+14]
add SectionOff, 16
ret
WriteResDirectory endp
WriteDataItem proc uses esi
invoke WriteResDirectory, 1
mov esi, SectionOff
add SectionOff, 8
invoke ConvProc
mov dword ptr[esi], 00000000h
mov dword ptr[esi+4], eax ; Data
mov esi, SectionOff
invoke xTableAdd, esi
xor edx, edx
mov dword ptr[esi+8], edx ; Codepage
mov dword ptr[esi+12], edx ; Reserved
add SectionOff, 4*4 ; Icon descriptor
ret
WriteDataItem endp
WriteIconDirectory proc uses ebx esi edi
mov eax, lpIconBuf
movzx eax, word ptr[eax+4]
mov ebx, eax
invoke WriteResDirectory, eax
mov eax, ebx
push eax
cdq
mov ecx, 8
mul ecx
mov esi, SectionOff
add SectionOff, eax
pop ebx
xor edi, edi
inc edi
@loop:
invoke ConvProc
mov dword ptr[esi], edi ; Icon identifier
or eax, 80000000h
mov dword ptr[esi+4], eax ; DATA_IS_DIRECTORY points to IconData
; Write IconData
call WriteDataItem
inc edi
add esi, 8
dec ebx
jnz @loop
ret
WriteIconDirectory endp
WriteGroupIconDirectory proc uses esi
invoke WriteResDirectory, 1
mov esi, SectionOff
add SectionOff, 8
invoke ConvProc
mov dword ptr[esi], 1
or eax, 80000000h
mov dword ptr[esi+4], eax ; points to Data
call WriteDataItem
ret
WriteGroupIconDirectory endp
InsertIconData proc uses esi edi ebx ecx T, Cnt: DWORD
; Calc RVA
mov eax, VirtOffset
add eax, SectionOff
sub eax, lpSection
mov ebx, T
; Write RVA
mov dword ptr[ebx], eax
; Calc ICONDIRENTRY offset for needed icon (Cnt)
mov esi, lpIconBuf
add esi, 6
mov eax, Cnt
shl eax, 4
add esi, eax
mov edx, [esi+8]
mov dword ptr[ebx+4], edx
; Write Icon data
mov esi, [esi+12]
add esi, lpIconBuf
mov edi, SectionOff
mov ecx, edx
@cpy:
lodsb
stosb
loop @cpy
add SectionOff, edx
ret
InsertIconData endp
InsertGroupIconData proc uses ebx esi edi T: DWORD
LOCAL Len: DWORD
LOCAL Count: WORD
mov Len, 0
mov Count, 0
; Calc RVA
mov eax, VirtOffset
add eax, SectionOff
sub eax, lpSection
mov ebx, T
; Write RVA
mov dword ptr[ebx], eax
; Write first 6 bytes (icon header)
mov esi, lpIconBuf
movzx edx, word ptr[esi+4] ; Image count
mov edi, SectionOff
mov ecx, 6
add Len, ecx
@cpy:
lodsb
stosb
loop @cpy
; Write icon descriptors from file to .rsrc section (each of 14 bytes)
@img_loop:
mov ecx, 14
add Len, ecx
inc Count
@cpy2:
lodsb
stosb
loop @cpy2
inc esi
inc esi
push word ptr[Count]
pop word ptr[edi-2] ; Image identifier (resource id)
dec edx
jnz @img_loop
mov ecx, Len
mov dword ptr[ebx+4], ecx
add SectionOff, ecx
ret
InsertGroupIconData endp
; Build .rsrc section
BuildRsrc proc uses esi edi ebx
push lpSection
pop SectionOff
invoke WriteResDirectory, 2
; ResourceEntry1: Icons
mov esi, SectionOff
add SectionOff, 16 ; ICON entry + Group Icon entry
call WriteIconDirectory ; Write ICON entry
mov dword ptr[esi], 00000003h ; ICON
mov dword ptr[esi+4], 80000020h ; DATA_IS_DIRECTORY, points to IconData
; ResourceEntry2: Group Icon
invoke ConvProc
mov dword ptr[esi+8], 0000000Eh ; GROUP ICON
or eax, 80000000h
mov dword ptr[esi+12], eax
call WriteGroupIconDirectory
; Write Icons
mov esi, offset xTable
mov edi, SectionOff
mov ecx, xTableOffset
dec ecx
xor ebx, ebx
@cpy1:
invoke InsertIconData, dword ptr[esi], ebx
inc ebx
add esi, 4
loop @cpy1
; Write Group Icon Descriptor
invoke InsertGroupIconData, dword ptr[esi]
add esi, 4
ret
BuildRsrc endp
; ------------------------------------------------------------------------
ProcessIcon proc uses edi
mov xTableOffset, 0
mov edi, offset xTable
mov ecx, (MAX_ICONS+1)*4
xor eax, eax
rep stosb
; Allocate memory for icon data
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, 20000h
mov lpSection, eax
invoke BuildRsrc
invoke ConvProc
mov SectionLen, eax
ret
ProcessIcon endp
; ------------------------------------------------------------------------
; ^^^^ EXE & DLL ^^^^
; Write icon from resource
WriteResIconData proc uses esi edi ecx hLib, dwID: DWORD
LOCAL rsrc: DWORD
invoke FindResource, hLib, dwID, RT_ICON
mov rsrc, eax
invoke SizeofResource, hLib, rsrc
push eax
invoke LoadResource, hLib, rsrc
pop ecx
test eax, eax
jz @err
test ecx, ecx
jz @err
mov esi, eax
mov edi, lpIconBuf
add edi, SectionOff
rep movsb
@err:
ret
WriteResIconData endp
; Enum callback, only first icon group will be processed
EnumResNameProc proc uses esi edi ebx hModule, lpszType, lpszName, lParam: DWORD
invoke FindResource, hModule, lpszName, lpszType
invoke LoadResource, hModule, eax
invoke LockResource, eax
; Find best suitable icon to display on preview button
push eax
invoke LookupIconIdFromDirectoryEx, eax, TRUE, CXICON, CYICON, LR_DEFAULTCOLOR
invoke FindResource, hModule, eax, RT_ICON
mov esi, eax
invoke LoadResource, hModule, eax
invoke LockResource, eax
mov edi, eax
invoke SizeofResource, hModule, esi
invoke CreateIconFromResourceEx, edi, eax, TRUE, 00030000h, CXICON, CYICON, LR_DEFAULTCOLOR
mov hSuitableIcon, eax
pop eax
.IF eax != 0
mov SectionOff, 6
mov esi, eax
mov edi, lpIconBuf
lodsd ; iReserved, iType
stosd
lodsw ; idCount
stosw
xor ecx, ecx
mov cx, ax
; Room for icon descriptors
mov eax, ecx
cdq
mov ebx, 16
mul ebx
add SectionOff, eax
@loop:
lodsd
stosd
lodsd
stosd
lodsd ; dwBytesInRes
push eax
stosd
; Offset
lodsw
movzx edx, ax
mov eax, SectionOff
stosd
invoke WriteResIconData, hModule, edx
pop eax
add SectionOff, eax
loop @loop
mov fProcessedOK, TRUE
.ENDIF
; Handle only first group
mov eax, FALSE
ret
EnumResNameProc endp
ProcessExeIcon proc hModule: DWORD
mov SectionOff, 0
mov hSuitableIcon, 0
invoke EnumResourceNames, hModule, RT_GROUP_ICON, offset EnumResNameProc, NULL
ret
ProcessExeIcon endp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -