您的位置:首页 > 其它

用UpdateResource修改EXE文件图标的多源码

2014-04-27 06:51 1156 查看


用UpdateResource修改EXE文件图标的多源码(已修正)

注:转帖请包函作者信息.(作者:菜新)

鄙视下百度空间,他姥姥...竟然限量字符40000字节!靠....

一年前初学VB时我对这个API就特感兴趣,听说这个API可以更改图标资源,就更感兴趣了,后来试了试,发现修改其它资源貌似没多大问题,唯独修改图标时无果,我发现所修改的图虽说已经写入到资源文件中了,但是就是无法显示。后来到网上查了下,发现用UpdateResource修改EXE图标的没一个成功的,大致都是发生成功写入,无法正常显示的问题。罢矣,当时就琢磨着把该问题先放放,等日后有时间再好好折腾。

无奈时间过得太快,忽忽悠悠就过了一年了,前几天,在整理去年的一些源码时发现了这个遗留在硬盘中的代码,一年前无奈自己所学浅溥,啥都不知道,但现在已经对API有了较深厚的认识,再加上对汇编的一些了解,我想此时不解决更待何时。

在折腾这个API的期间也发生不少问题,最让我自责的就是差点被 CreateFile 这个API给Game Over,这个小伟知道(又是小伟?没办法啊,谁要咱和小伟太有缘了~)。还好自己最终醒悟,否则真的要好好鄙视鄙视自己。最初修改时还是和一年前一个样,这时我一直在回想一样年遇到这个问题的问题:所写图标的数据是不是完整的写到了资源文件中?想到此,我用eXeScope(一个PE资源文件查看工具)看了下写入到资源文件中的十六进制,又用UltraEdit-32以十六进制查看ico文件中的数据,发现没问题啊?一字节一字节都对得上,那问题出在哪了?没法,继续在Google游荡,终于找了一份有效的资料(网址现在不知扔哪去了),全E文,看得难受,不过大致的意思是说ICON是由一个结构组成,同PE那些什么NT头,DOS头的差不多,而所显示的图像数据包函于ICON类型结构的dwImageOffset偏移处。呵,这下总算搞明白为什么直接把ICON文件写入到资源文件中显示不了的问题了,也就是说在dwImageOffset偏移位置处才是咱所需要的图像数据,这不就啥都OK了么,爷爷的,原来咱从一开始就被ICON文件整得稀里糊涂,靠MS,当然也鄙视下自己的无知。另外还好找到的那份资料有点人性,把结构给咱标出来了,那么现在一切都顺理成章,不说多了,上代码:

===============================================

Delphi Code:

===============================================

//请自行添加到 Type 处

PICONDIRENTRY = ^ICONDIRENTRY;

ICONDIRENTRY = packed record

bWidth: Byte;

bHeight: Byte;

bColorCount: Byte;

bReserved: Byte;

wPlanes: Word;

wBitCount: Word;

dwBytesInRes: DWORD;

dwImageOffset: DWORD;

end;

PICONDIR = ^ICONDIR;

ICONDIR = packed record

idReserved: Word;

idType: Word;

idCount: Word;

idEntries: ICONDIRENTRY;

end;

PGRPICONDIRENTRY = ^GRPICONDIRENTRY;

GRPICONDIRENTRY = packed record

bWidth: Byte;

bHeight: Byte;

bColorCount: Byte;

bReserved: Byte;

wPlanes: Word;

wBitCount: Word;

dwBytesInRes: DWORD;

nID: Word;

end;

PGRPICONDIR = ^GRPICONDIR;

GRPICONDIR = packed record

idReserved: Word;

idType: Word;

idCount: Word;

idEntries: GRPICONDIRENTRY;

end;

//////////////////////////////////////////////

//函数说明:修改EXE图标

//

//参 数:IconFile 图标文件

// ExeFile 被修改的EXE文件

//

//返回值: 成功为True,否则False

/////////////////////////////////////////////

function ChangeExeIcon(IcoFile, ExeFile: string): Boolean;

var

stID: ICONDIR;

stGID: GRPICONDIR;

pGrpIcon: PBYTE;

pIcon: PBYTE;

hUpdate: DWORD;

nSize, nGSize: DWORD;

hFile: THandle;

dwReserved: DWORD;

ret: Boolean;

begin

Result := False;

hFile := CreateFile(PChar(IcoFile), GENERIC_READ, 0, nil, OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL, 0);

if hFile = INVALID_HANDLE_VALUE then

Exit;

try

ReadFile(hFile, stID, Sizeof(ICONDIR), dwReserved, nil);

nSize := stID.idEntries.dwBytesInRes;

GetMem(pIcon, nSize);

SetFilePointer(hFile, stID.idEntries.dwImageOffset, nil, FILE_BEGIN);

ReadFile(hFile, pIcon^, nSize, dwReserved, nil);

stGID.idType := 1;

stGID.idCount := stID.idCount;

stGID.idReserved := 0;

CopyMemory(@stGID.idEntries.bWidth, @stID.idEntries.bWidth, 12);

stGID.idEntries.nID := 0;

nGSize := Sizeof(GRPICONDIR);

GetMem(pGrpIcon, nGSize);

CopyMemory(pGrpIcon, @stGID, nGSize);

hUpdate := BeginUpdateResource(PChar(ExeFile), False);

try

ret := UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(1), 0, pGrpIcon, nGSize);

ret := UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), 0, pIcon, nSize);

finally

EndUpdateResource(hUpdate, False);

end;

finally

CloseHandle(hFile);

end;

Result := ret;

end;

===============================================

VB Code:

===============================================

Option Explicit

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long,
ByVal hTemplateFile As Long) As Long

Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long

Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long

Private Declare Function BeginUpdateResource Lib "kernel32" Alias "BeginUpdateResourceA" (ByVal pFileName As String, ByVal bDeleteExistingResources As Long) As Long

Private Declare Function UpdateResource Lib "kernel32" Alias "UpdateResourceA" (ByVal hUpdate As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal wLanguage As Long, lpData As Any, ByVal cbData As Long) As Long

Private Declare Function EndUpdateResource Lib "kernel32" Alias "EndUpdateResourceA" (ByVal hUpdate As Long, ByVal fDiscard As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Declare Function GetLastError Lib "kernel32" () As Long

Private Const INVALID_HANDLE_VALUE = -1

Private Const GENERIC_READ = &H80000000

Private Const FILE_ATTRIBUTE_NORMAL = &H80

Private Const FILE_BEGIN = 0

Private Const OPEN_EXISTING = 3

Private Const RT_ICON = 3&

Private Const DIFFERENCE As Long = 11

Private Const RT_GROUP_ICON As Long = (RT_ICON + DIFFERENCE)

Private Type ICONDIRENTRY

bWidth As Byte

bHeight As Byte

bColorCount As Byte

bReserved As Byte

wPlanes As Integer

wBitCount As Integer

dwBytesInRes As Long

dwImageOffset As Long

End Type

Private Type ICONDIR

idReserved As Integer

idType As Integer

idCount As Integer

'idEntries As ICONDIRENTRY

End Type

Private Type GRPICONDIRENTRY

bWidth As Byte

bHeight As Byte

bColorCount As Byte

bReserved As Byte

wPlanes As Integer

wBitCount As Integer

dwBytesInRes As Long

nID As Integer

End Type

Private Type GRPICONDIR

idReserved As Integer

idType As Integer

idCount As Integer

idEntries As GRPICONDIRENTRY

End Type

'//////////////////////////////////////////////

'//函数说明:修改EXE图标

'//

'//参 数:IconFile 图标文件

'// ExeFile 被修改的EXE文件

'//

'//返回值: 成功为True,否则False

'/////////////////////////////////////////////////////

Private Function ChangeExeIcon(ByVal IconFile As String, ByVal ExeFile As String) As Boolean

On Error GoTo cw

Dim stID As ICONDIR

Dim stIDE As ICONDIRENTRY

Dim stGID As GRPICONDIR

Dim hFile As Long

Dim pIcon() As Byte, pGrpIcon() As Byte

Dim nSize As Long, nGSize As Long

Dim dwReserved As Long

Dim hUpdate As Long

Dim ret As Long

hFile = CreateFile(IconFile, GENERIC_READ, 0, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)

If hFile = INVALID_HANDLE_VALUE Then Exit Function

ret = ReadFile(hFile, stID, Len(stID), dwReserved, ByVal 0&)

If ret = 0 Then GoTo cw

ret = ReadFile(hFile, stIDE, Len(stIDE), dwReserved, ByVal 0&)

nSize = stIDE.dwBytesInRes

ReDim pIcon(nSize - 1)

SetFilePointer hFile, stIDE.dwImageOffset, ByVal 0&, FILE_BEGIN

ret = ReadFile(hFile, pIcon(0), nSize, dwReserved, ByVal 0&)

If ret = 0 Then GoTo cw

With stGID

.idType = 1

.idCount = stID.idCount

.idReserved = 0

CopyMemory stGID.idEntries, stIDE, 12

.idEntries.nID = 0

End With

nGSize = Len(stGID)

ReDim pGrpIcon(nGSize - 1)

CopyMemory pGrpIcon(0), stGID, nGSize

hUpdate = BeginUpdateResource(ExeFile, False)

ret = UpdateResource(hUpdate, RT_GROUP_ICON, 1, 0, pGrpIcon(0), nGSize)

ret = UpdateResource(hUpdate, RT_ICON, 1, 0, pIcon(0), nSize)

EndUpdateResource hUpdate, False

If ret = 0 Then GoTo cw

ChangeExeIcon = True

cw:

CloseHandle hFile

End Function

===============================================

VC++ Code:

===============================================

#include <stdio.h>

#include <windows.h>

#include <tchar.h>

struct ICONDIRENTRY

{

BYTE bWidth;

BYTE bHeight;

BYTE bColorCount;

BYTE bReserved;

WORD wPlanes;

WORD wBitCount;

DWORD dwBytesInRes;

DWORD dwImageOffset;

};

struct ICONDIR

{

WORD idReserved;

WORD idType;

WORD idCount;

//ICONDIRENTRY idEntries;

};

struct GRPICONDIRENTRY

{

BYTE bWidth;

BYTE bHeight;

BYTE bColorCount;

BYTE bReserved;

WORD wPlanes;

WORD wBitCount;

DWORD dwBytesInRes;

WORD nID;

};

struct GRPICONDIR

{

WORD idReserved;

WORD idType;

WORD idCount;

GRPICONDIRENTRY idEntries;

};

//////////////////////////////////////////////

//函数说明:修改EXE图标

//

//参 数:IconFile 图标文件

// ExeFile 被修改的EXE文件

//

//返回值: 成功为True,否则False

/////////////////////////////////////////////

bool ChangeExeIcon(LPWSTR IconFile, LPWSTR ExeFile)

{

ICONDIR stID;

ICONDIRENTRY stIDE;

GRPICONDIR stGID;

HANDLE hFile;

DWORD nSize, nGSize, dwReserved;

HANDLE hUpdate;

PBYTE pIcon, pGrpIcon;

BOOL ret;

hFile = CreateFile(IconFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile == INVALID_HANDLE_VALUE)

{

return false;

}

ZeroMemory(&stID, sizeof(ICONDIR));

ret = ReadFile(hFile, &stID, sizeof(ICONDIR), &dwReserved, NULL);

ZeroMemory(&stIDE, sizeof(ICONDIRENTRY));

ret = ReadFile(hFile, &stIDE, sizeof(ICONDIRENTRY), &dwReserved, NULL);

nSize = stIDE.dwBytesInRes;

pIcon = (PBYTE)malloc(nSize);

SetFilePointer(hFile, stIDE.dwImageOffset, NULL, FILE_BEGIN);

ret = ReadFile(hFile, (LPVOID)pIcon, nSize, &dwReserved, NULL);

if (!ret)

{

CloseHandle(hFile);

return false;

}

ZeroMemory(&stGID, sizeof(GRPICONDIR));

stGID.idCount = stID.idCount;

stGID.idReserved = 0;

stGID.idType = 1;

CopyMemory(&stGID.idEntries, &stIDE, 12);

stGID.idEntries.nID = 0;

nGSize = sizeof(GRPICONDIR);

pGrpIcon = (PBYTE)malloc(nGSize);

CopyMemory(pGrpIcon, &stGID, nGSize);

hUpdate = BeginUpdateResource(ExeFile, false);

ret = UpdateResource(hUpdate, RT_GROUP_ICON, MAKEINTRESOURCE(1), 0, (LPVOID)pGrpIcon, nGSize);

ret = UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), 0, (LPVOID)pIcon, nSize);

EndUpdateResource(hUpdate, false);

if (!ret)

{

CloseHandle(hFile);

return false;

}

CloseHandle(hFile);

return true;

}

===============================================

ASM Code:

===============================================

.386

.model flat,stdcall

option casemap:none

include windows.inc

include user32.inc

includelib user32.lib

include kernel32.inc

includelib kernel32.lib

ICONDIRENTRY STRUCT

bWidth BYTE ?

bHeight BYTE ?

bColorCount BYTE ?

bReserved BYTE ?

wPlanes WORD ?

wBitCount WORD ?

dwBytesInRes DWORD ?

dwImageOffset DWORD ?

ICONDIRENTRY ENDS

ICONDIR STRUCT

idReserved WORD ?

idType WORD ?

idCount WORD ?

;idEntries ICONDIRENTRY <>

ICONDIR ENDS

GRPICONDIRENTRY STRUCT

bWidth BYTE ?

bHeight BYTE ?

bColorCount BYTE ?

bReserved BYTE ?

wPlanes WORD ?

wBitCount WORD ?

dwBytesInRes DWORD ?

nID WORD ?

GRPICONDIRENTRY ENDS

GRPICONDIR STRUCT

idReserved WORD ?

idType WORD ?

idCount WORD ?

idEntries GRPICONDIRENTRY <>

GRPICONDIR ENDS

.data

szIcon db 'a.ico', 0

szFile db 'a.exe', 0

.code

//////////////////////////////////////////////

//函数说明:修改EXE图标

//

//参 数:IconFile 图标文件

// ExeFile 被修改的EXE文件

//

//返回值: 成功为True,否则False

/////////////////////////////////////////////

_ChangeExeIcon proc IconFile, ExeFile

local @stID: ICONDIR

local @stIDE: ICONDIRENTRY

local @stGID: GRPICONDIR

local @hFile: DWORD

local @dwReserved: DWORD

local @nSize: DWORD

local @nGSize: DWORD

local @pIcon: DWORD

local @pGrpIcon: DWORD

local @hUpdate: DWORD

local @ret: DWORD

invoke CreateFile, IconFile, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL

mov @hFile, eax

.if eax == INVALID_HANDLE_VALUE

xor eax, eax

ret

.endif

invoke RtlZeroMemory, addr @stID, sizeof @stID

invoke ReadFile, @hFile, addr @stID, sizeof @stID, addr @dwReserved, NULL

invoke RtlZeroMemory, addr @stIDE, sizeof @stIDE

invoke ReadFile, @hFile, addr @stIDE, sizeof @stIDE, addr @dwReserved, NULL

push @stIDE.dwBytesInRes

pop @nSize

invoke GlobalAlloc, GPTR, @nSize

mov @pIcon, eax

invoke SetFilePointer, @hFile, @stIDE.dwImageOffset, NULL, FILE_BEGIN

invoke ReadFile, @hFile, @pIcon, @nSize, addr @dwReserved, NULL

cmp eax, 0

je err

invoke RtlZeroMemory, addr @stGID, sizeof @stGID

push @stID.idCount

pop @stGID.idCount

mov @stGID.idReserved, 0

mov @stGID.idType, 1

invoke RtlMoveMemory, addr @stGID.idEntries, addr @stIDE, 12

mov @stGID.idEntries.nID, 0

mov @nGSize, sizeof @stGID

invoke GlobalAlloc, GPTR, @nGSize

mov @pGrpIcon, eax

invoke RtlMoveMemory, @pGrpIcon, addr @stGID, @nGSize

;开始修改

invoke BeginUpdateResource, ExeFile, FALSE

mov @hUpdate, eax

invoke UpdateResource, @hUpdate, RT_GROUP_ICON, 1, 0, @pGrpIcon, @nGSize

invoke UpdateResource, @hUpdate, RT_ICON, 1, 0, @pIcon, @nSize

mov @ret, eax

invoke EndUpdateResource, @hUpdate, FALSE

.if @ret == FALSE

jmp err

.endif

;成功后到此一日游

invoke GlobalFree, @pIcon

invoke CloseHandle, @hFile

mov eax, 1

ret

err:

;失败后到此一日游

invoke GlobalFree, @pIcon

invoke CloseHandle, @hFile

xor eax, eax

ret

_ChangeExeIcon endp

;==========================程序入口=============================

start:

invoke _ChangeExeIcon, offset szIcon, offset szFile

invoke ExitProcess, NULL

end start
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: