Интересная проблема при выдирании иконки из exe
Не много раньше я открывал тему "Вытащить из .exe или .dll иконку "
Creat0R Предложил мне функцию.
FileExtractIcon("shell32.dll", @DesktopDir & "\Icon.ico", -20)
Одним из недостатков этой функции был тот что иконки на выходе получаются на чёрном фоне.
Тогда beve предложил более сложную функцию которую впоследствии Creat0R оптимизировав её
убрал всё лишние, на выходе получилась функция которая нормально справлялась со своей работой.
До тех пор пока мне не попался случайно файл crack.exe и моя програмка которую я делаю при попытке
выдрать эту иконку тут же гаснет, я испытывал на многих файлах и 99 из 100 функция работает отлично
В SciTE при отладке этой функции пишет ошибку
Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4))))
Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight(^ ERROR
Кстати професиональная прога Articons Pro хоть и не гасла но тоже отказывалась вытаскивать эти иконки
(их кстати там две) А вот первая функция которую мне предложил Creat0R
FileExtractIcon("crack.exe", @DesktopDir & "\Icon.ico", -1)
Вытащила их без проблем только как я уже говорил на чёрном фоне.
Только прога Koda в которой есть фишка которая подставляет иконки в вашу программу и там можно эту иконку
вытащить, справилась с этим crack.exe без проблем.Но как узнать как она это сделала?
Всё таки интересно что за ошибка вылезает в этой функции
Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4))))
Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight(^ ERROR
И она напрочь отказывается работать с этим crack.exe
Ещё раз повторю 99 из 100 функция работает отлично.
Файл crack.exe Прилагаю.
Код:
#include <WinAPI.au3>
Global $aEN[1]
$sSrc = @SystemDir & "\shell32.dll" ;"crack.exe"
$sOut = @DesktopDir & "\MyIcon.ico"
_FileExtractIcon($sSrc, -1, $sOut)
Func _FileExtractIcon($sINFILE, $iICON, $sOUTICO, $iPATH = 0, $iSaveAsPng = 0)
Local Const $RT_GROUP_ICON = 14
Local $hINST, $iGN = "", $HFIND, $aSIZE, $hLOAD, $HLOCK, $TRES, $sDATA, $aRet[2]
If Not FileExists($sINFILE) And Not IsPtr($sINFILE) Then Return SetError(1, 0, 0)
If Not IsInt($iICON) Then Return SetError(2, 0, 0)
If IsPtr($sINFILE) Then
$hINST = $sINFILE
Else
$hINST = _WinAPI_LoadLibraryEx($sINFILE, 2)
If Not $hINST Then Return SetError(3, 0, 0)
EndIf
If Not IsPtr($hINST) Then Return SetError(3, 0, 0)
__ResourceEnumNames($hINST, $RT_GROUP_ICON)
If @error Then
_WinAPI_FreeLibrary($hINST)
Return SetError(4, 0, 0)
EndIf
For $I = 1 To $aEN[0]
If $I = StringReplace($iICON, "-", "") Then
$iGN = $aEN[$I]
ExitLoop
EndIf
Next
If $iGN = "" Then
_WinAPI_FreeLibrary($hINST)
Return SetError(5, 0, 0)
EndIf
$HFIND = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hINST, "str", $iGN, "long", $RT_GROUP_ICON)
If $HFIND[0] = 0 Then
_WinAPI_FreeLibrary($hINST)
Return SetError(6, 0, 0)
EndIf
$aSIZE = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hINST, "int", $HFIND[0])
If $aSIZE[0] = 0 Then
_WinAPI_FreeLibrary($hINST)
Return SetError(7, 0, 0)
EndIf
$hLOAD = DllCall("kernel32.dll", "int", "LoadResource", "int", $hINST, "int", $HFIND[0])
If $hLOAD[0] = 0 Then
_WinAPI_FreeLibrary($hINST)
Return SetError(8, 0, 0)
EndIf
$HLOCK = DllCall("kernel32.dll", "int", "LockResource", "int", $hLOAD[0])
If $HLOCK[0] = 0 Then
_WinAPI_FreeLibrary($hINST)
Return SetError(9, 0, 0)
EndIf
$TRES = DllStructCreate("byte[" & $aSIZE[0] & "]", $HLOCK[0])
If Not IsDllStruct($TRES) Then
_WinAPI_FreeLibrary($hINST)
Return SetError(10, 0, 0)
EndIf
$sDATA = DllStructGetData($TRES, 1)
If $sDATA = "" Then
_WinAPI_FreeLibrary($hINST)
Return SetError(11, 0, 0)
EndIf
__FreeResource($hLOAD[0])
If Not IsPtr($sINFILE) Then _WinAPI_FreeLibrary($hINST)
Dim $aEN[1]
$aRet[0] = $sINFILE
$aRet[1] = $sDATA
;_Exticondata()
Local $aID = $aRet
Local Const $RT_ICON = 3
Local $hINST, $AHDR, $aRet[1][2]
If Not IsArray($aID) Then Return SetError(1, 0, 0)
If Not FileExists($aID[0]) And Not IsPtr($aID[0]) Then Return SetError(2, 0, 0)
If IsPtr($aID[0]) Then
$hINST = $aID[0]
Else
$hINST = _WinAPI_LoadLibraryEx($aID[0], 2)
If Not $hINST Then Return SetError(3, 0, 0)
EndIf
If Not IsPtr($hINST) Then Return SetError(3, 0, 0)
$aRet[0][0] = Dec(__Rb(StringMid($aID[1], 11, 4)))
ReDim $aRet[$aRet[0][0] + 1][2]
$AHDR = StringRegExp(StringTrimLeft(BinaryMid($aID[1], 7), 2), "(.{28})", 3)
For $I = 1 To $aRet[0][0]
Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4))))
$aRet[$I][0] = StringTrimRight($AHDR[$I - 1], 4)
$aRet[$I][1] = $AGID[1]
__FreeResource($AGID[0])
Next
If Not IsPtr($aID[0]) Then _WinAPI_FreeLibrary($hINST)
;_Createiconfile($aID, $aSEL, $sOUTICO, $iPATH = 0, $iSaveAsPng = 0)
Local $aSEL = $iICON
$aID = $aRet
If Not IsArray($aID) Then Return SetError(1, 0, 0)
Local $iCNT, $sHDR, $OFFSET, $sDBYTE, $iMICON = "", $FO, $FW, $eSEL[$aID[0][0]], $iCRT = 18
If $iPATH <> 0 Then $iCRT = 26
If Not IsArray($aSEL) Then
For $I = 0 To UBound($eSEL) - 1
$eSEL[$I] = $I + 1
Next
$aSEL = $eSEL
EndIf
If UBound($aSEL) = 1 And StringInStr(StringTrimLeft($aID[$aSEL[0]][1], 2), "504E47") Then
If $iSaveAsPng Then $sOUTICO = StringReplace($sOUTICO, ".ico", ".png")
EndIf
$iCNT = UBound($aSEL)
$sHDR = "0x00000100" & __Rb(Hex($iCNT, 4))
$OFFSET = ($iCNT * 16) + 6
For $I = 0 To UBound($aSEL) - 1
$sDBYTE = Dec(__Rb(StringMid($aID[$aSEL[$I]][0], 17, 8)))
$sHDR &= $aID[$aSEL[$I]][0] & __Rb(Hex($OFFSET))
$OFFSET += $sDBYTE
If StringRight($sOUTICO, 4) = ".png" Then
$sHDR = ""
$iMICON &= $aID[$aSEL[$I]][1]
Else
$iMICON &= StringTrimLeft($aID[$aSEL[$I]][1], 2)
EndIf
Next
$FO = FileOpen($sOUTICO, $iCRT)
If $FO = -1 Then Return SetError(2, 0, 0)
$FW = FileWrite($FO, $sHDR & $iMICON)
If $FW = 0 Then
FileClose($FO)
Return SetError(3, 0, 0)
EndIf
FileClose($FO)
Return SetError(0, 0, 1)
EndFunc
Func __FreeResource($HGLBRESOURCE)
DllCall("kernel32.dll", "int", "FreeResource", "int", $HGLBRESOURCE)
EndFunc
Func __GetIconData($hMODULE, $iON)
Local Const $RT_ICON = 3
Local $HFIND, $aSIZE, $hLOAD, $HLOCK, $TRES, $aRet[2]
$HFIND = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hMODULE, "str", "#" & $iON, "long", $RT_ICON)
$aSIZE = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hMODULE, "int", $HFIND[0])
$hLOAD = DllCall("kernel32.dll", "int", "LoadResource", "int", $hMODULE, "int", $HFIND[0])
$HLOCK = DllCall("kernel32.dll", "int", "LockResource", "int", $hLOAD[0])
$TRES = DllStructCreate("byte[" & $aSIZE[0] & "]", $HLOCK[0])
$aRet[0] = $HLOCK[0]
$aRet[1] = DllStructGetData($TRES, 1)
Return $aRet
EndFunc
Func __Rb($sBYTE)
Local $AX = StringRegExp($SBYTE, "(.{2})", 3), $SX = ""
For $I = UBound($AX) - 1 To 0 Step -1
$SX &= $AX[$I]
Next
Return $SX
EndFunc
Func __ResourceEnumNames($hMODULE, $iTYPE)
Local $aRet, $stCB
If Not IsPtr($hMODULE) Then Return SetError(1, 0, 0)
$stCB = DllCallbackRegister("__ResourceEnumNames_Proc", "int", "int_ptr;int_ptr;int_ptr;int_ptr")
$aRet = DllCall("kernel32.dll", "int", "EnumResourceNamesW", "ptr", $hMODULE, "int", $iTYPE, "ptr", DllCallbackGetPtr($stCB), "ptr", 0)
DllCallbackFree($stCB)
If $aRet[0] <> 1 Then Return SetError(2, 0, 0)
Return SetError(0, 0, 1)
EndFunc
Func __ResourceEnumNames_Proc($hMODULE, $pTYPE, $pNAME, $lPARAM)
Local $aSIZE = DllCall("kernel32.dll", "int", "GlobalSize", "ptr", $pNAME), $tBUF
If $aSIZE[0] Then
$tBUF = DllStructCreate("wchar[" & $aSIZE[0] & "]", $pNAME)
ReDim $aEN[UBound($aEN) + 1]
$aEN[0] += 1
$aEN[UBound($aEN) - 1] = DllStructGetData($tBUF, 1)
Else
ReDim $aEN[UBound($aEN) + 1]
$aEN[0] += 1
$aEN[UBound($aEN) - 1] = "#" & $pNAME
EndIf
Return 1
EndFunc
|