Sign in to follow this  
Followers 0
Digisoul

Question About Dll Structure

10 posts in this topic

#1 ·  Posted (edited)

Hi there,

I need to know about a dll Structure that how can i make the following structure?

here is a VC Structure,

typedef struct
{
    WORD           idReserved;   // Reserved (must be 0)
    WORD           idType;       // Resource Type (1 for icons)
    WORD           idCount;      // How many images?
    ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;


typedef struct
{
    BYTE        bWidth;          // Width, in pixels, of the image
    BYTE        bHeight;         // Height, in pixels, of the image
    BYTE        bColorCount;     // Number of colors in image (0 if >=8bpp)
    BYTE        bReserved;       // Reserved ( must be 0)
    WORD        wPlanes;         // Color Planes
    WORD        wBitCount;       // Bits per pixel
    DWORD       dwBytesInRes;    // How many bytes in this resource?
    DWORD       dwImageOffset;   // Where in the file is this image?
} ICONDIRENTRY, *LPICONDIRENTRY;

i code it like this:

Local $IconDir = "ushort Reserved;ushort ResourceType;ushort ImageCount"

Local $IconDirEntry = "BYTE Width;BYTE Height;BYTE Colors;BYTE Reserved2;ushort Planes;ushort BitsPerPixel;DWORD ImageSize;ushort ResourceID"

Now i am unable to understand the "ICONDIRENTRY idEntries[1]" element of ICONDIR Structure in VC , how can i do this in AutoIt ?

Thanks in Advance.

Edited by Digisoul

73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites



Of course that's not it jaberwocky6669.

@Digisoul, just append as much $IconDirEntry-s as you want to your $IconDir.

But if you are reading then it would be better (simpler, at least often) to make raw structure, this means all bytes, in calculated size and interpret it afterwards as number of ICONDIRENTRYs.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

@Digisoul, just append as much $IconDirEntry-s as you want to your $IconDir.

well i tried it first but its become corrupted after updating it in RT_GROUP_ICON.

But if you are reading then it would be better (simpler, at least often) to make raw structure, this means all bytes, in calculated size and interpret it afterwards as number of ICONDIRENTRYs.

what is this? Posted Image

73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites

Let me see what you tried.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Let me see what you tried.

please see the attachment, here is my rough attempt to update the icon, its currently for Au3 exe only.

updateIcon.au3


73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites

Yes, I see. Here's how it goes...

Global $sModule = @ScriptDir & "\qq.exe" ; some PE file you want to add icon to
Global $iResName = 234 ; random RT_GROUP_ICON name
Global $iResLang = 0 ; Neutral language for the resource
Global $iSubResName = 457 ; random RT_ICON name
Global $sResFile = "Ico.ico"

; First you read your icon to raw (byte) structure
Local $tBinary = DllStructCreate("byte[" & FileGetSize($sResFile) & "]") ; make the buffer in required size
Local $hResFile = FileOpen($sResFile, 16) ; open file handle (read binary)
DllStructSetData($tBinary, 1, FileRead($hResFile)) ; readt to structure
FileClose($hResFile) ; close handle
; There. Now you have all the data you would need in one memory space for easy access.

; Let's find how many icons are in read icon. This might help http://en.wikipedia.org/wiki/ICO_(file_format).
; Out of that I can write (ICONDIR structure where Body is raw ICONDIRENTRY-s):
Local $tResource = DllStructCreate("word;" & _
        "word Type;" & _
        "word ImageCount;" & _
        "byte Body[" & DllStructGetSize($tBinary) - 6 & "]", _ ; This is the rest of the data. -6 is there to be the same sise as $tBinary because three words are 6 bytes.
        DllStructGetPtr($tBinary)) ; copying it from $tBinary
; And now reading the count:
Local $iIconCount = DllStructGetData($tResource, "ImageCount")

;*******************************************************************
; Icons are one of the few special res types. Their specificity is that they are stored in two different places inside the PE file.
; General data is stored as (in) RT_GROUP_ICON and the binary body of the icon is in RT_ICON.
; RT_GROUP_ICON is a sort of dispatch.
;*******************************************************************

; This structure is how RT_GROUP_ICON looks like. It's very similar to ICONDIR structure (don't let it confuse you)
Local $tIconGroupHeader = DllStructCreate("word;" & _
        "word Type;" & _
        "word ImageCount;" & _
        "byte Body[" & $iIconCount * 14 & "]")

DllStructSetData($tIconGroupHeader, 1, DllStructGetData($tResource, 1)) ; this is that reserved field from the ICO specification (it's always 0)
DllStructSetData($tIconGroupHeader, "Type", DllStructGetData($tResource, "Type")) ; this is the type. For icons it's 1 (for cursor it's 2)
DllStructSetData($tIconGroupHeader, "ImageCount", $iIconCount) ; aha!

Local $tInputIconHeader
Local $tGroupIconData

; Initializing res modification procedure
Local $aCall = DllCall("kernel32.dll", "handle", "BeginUpdateResourceW", "wstr", $sModule, "int", 0)
; ...checking errors here...

; Get that handle:
Local $hHandle = $aCall[0]

Local $iEnumIconName = $iSubResName ; I'm gonna assume this one doesn't exist to be overwritten

; Loop thru all icons. They will all be written to PE file.
For $i = 1 To $iIconCount

    ; Structure below is read from $sResFile (ICO specification - ICONDIRENTRY)
    $tInputIconHeader = DllStructCreate("byte Width;" & _
            "byte Height;" & _
            "byte Colors;" & _
            "byte;" & _
            "word Planes;" & _
            "word BitPerPixel;" & _
            "dword BitmapSize;" & _
            "dword BitmapOffset", _
            DllStructGetPtr($tResource, "Body") + ($i - 1) * 16) ; every new structure is 16 bytes ahead

    ; RT_GROUP_ICON Body (see the simplcity I was talking about)
    $tGroupIconData = DllStructCreate("byte Width;" & _
            "byte Height;" & _
            "byte Colors;" & _
            "byte;" & _
            "word Planes;" & _
            "word BitPerPixel;" & _
            "dword BitmapSize;" & _
            "word OrdinalName;", _
            DllStructGetPtr($tIconGroupHeader, "Body") + ($i - 1) * 14) ; every new structure is 14 bytes ahead

    ; Copy from one structure to another
    DllStructSetData($tGroupIconData, "Width", DllStructGetData($tInputIconHeader, "Width"))
    DllStructSetData($tGroupIconData, "Height", DllStructGetData($tInputIconHeader, "Height"))
    DllStructSetData($tGroupIconData, "Colors", DllStructGetData($tInputIconHeader, "Colors"))
    DllStructSetData($tGroupIconData, 4, DllStructGetData($tInputIconHeader, 4)) ; this is reserved field (irrelevant actually)
    DllStructSetData($tGroupIconData, "Planes", DllStructGetData($tInputIconHeader, "Planes"))
    DllStructSetData($tGroupIconData, "BitPerPixel", DllStructGetData($tInputIconHeader, "BitPerPixel"))
    DllStructSetData($tGroupIconData, "BitmapSize", DllStructGetData($tInputIconHeader, "BitmapSize"))

    ; Set the name
    DllStructSetData($tGroupIconData, "OrdinalName", $iEnumIconName) ; That's the only difference between the two structures

    ; Write this new icon to PE file:
    DllCall("kernel32.dll", "bool", "UpdateResourceW", _
            "handle", $hHandle, _
            "int", 3, _ ; RT_ICON
            "int", $iEnumIconName, _
            "word", $iResLang, _
            "ptr", DllStructGetPtr($tResource) + DllStructGetData($tInputIconHeader, "BitmapOffset"), _ ; This is icon's data.
            "dword", DllStructGetData($tInputIconHeader, "BitmapSize")) ; and it's size
    ; ...checking errors here...

    ; New name for te icon
    $iEnumIconName += 1 ; This is usually done by incrementing the last one by one (can be any other scheme)
Next

; Finally write RT_GROUP_ICON:
DllCall("kernel32.dll", "bool", "UpdateResourceW", _
                "handle", $hHandle, _
                "int", 14, _ ; RT_GROUP_ICON
                "int", $iResName, _ ; Can be string too of course. In that case it's ..."wstr", StringUpper($sName), ...
                "word", $iResLang, _
                "ptr", DllStructGetPtr($tIconGroupHeader), _
                "dword", DllStructGetSize($tIconGroupHeader))
    ; ...checking errors here...

; End res modification procedure
DllCall("kernel32.dll", "bool", "EndUpdateResourceW", "handle", $hHandle, "int", 0)

; The End

That helps?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Yes, I see. Here's how it goes...

Global $sModule = @ScriptDir & "\qq.exe" ; some PE file you want to add icon to
Global $iResName = 234 ; random RT_GROUP_ICON name
Global $iResLang = 0 ; Neutral language for the resource
Global $iSubResName = 457 ; random RT_ICON name
Global $sResFile = "Ico.ico"

; First you read your icon to raw (byte) structure
Local $tBinary = DllStructCreate("byte[" & FileGetSize($sResFile) & "]") ; make the buffer in required size
Local $hResFile = FileOpen($sResFile, 16) ; open file handle (read binary)
DllStructSetData($tBinary, 1, FileRead($hResFile)) ; readt to structure
FileClose($hResFile) ; close handle
; There. Now you have all the data you would need in one memory space for easy access.

; Let's find how many icons are in read icon. This might help http://en.wikipedia.org/wiki/ICO_(file_format).
; Out of that I can write (ICONDIR structure where Body is raw ICONDIRENTRY-s):
Local $tResource = DllStructCreate("word;" & _
        "word Type;" & _
        "word ImageCount;" & _
        "byte Body[" & DllStructGetSize($tBinary) - 6 & "]", _ ; This is the rest of the data. -6 is there to be the same sise as $tBinary because three words are 6 bytes.
        DllStructGetPtr($tBinary)) ; copying it from $tBinary
; And now reading the count:
Local $iIconCount = DllStructGetData($tResource, "ImageCount")

;*******************************************************************
; Icons are one of the few special res types. Their specificity is that they are stored in two different places inside the PE file.
; General data is stored as (in) RT_GROUP_ICON and the binary body of the icon is in RT_ICON.
; RT_GROUP_ICON is a sort of dispatch.
;*******************************************************************

; This structure is how RT_GROUP_ICON looks like. It's very similar to ICONDIR structure (don't let it confuse you)
Local $tIconGroupHeader = DllStructCreate("word;" & _
        "word Type;" & _
        "word ImageCount;" & _
        "byte Body[" & $iIconCount * 14 & "]")

DllStructSetData($tIconGroupHeader, 1, DllStructGetData($tResource, 1)) ; this is that reserved field from the ICO specification (it's always 0)
DllStructSetData($tIconGroupHeader, "Type", DllStructGetData($tResource, "Type")) ; this is the type. For icons it's 1 (for cursor it's 2)
DllStructSetData($tIconGroupHeader, "ImageCount", $iIconCount) ; aha!

Local $tInputIconHeader
Local $tGroupIconData

; Initializing res modification procedure
Local $aCall = DllCall("kernel32.dll", "handle", "BeginUpdateResourceW", "wstr", $sModule, "int", 0)
; ...checking errors here...

; Get that handle:
Local $hHandle = $aCall[0]

Local $iEnumIconName = $iSubResName ; I'm gonna assume this one doesn't exist to be overwritten

; Loop thru all icons. They will all be written to PE file.
For $i = 1 To $iIconCount

    ; Structure below is read from $sResFile (ICO specification - ICONDIRENTRY)
    $tInputIconHeader = DllStructCreate("byte Width;" & _
            "byte Height;" & _
            "byte Colors;" & _
            "byte;" & _
            "word Planes;" & _
            "word BitPerPixel;" & _
            "dword BitmapSize;" & _
            "dword BitmapOffset", _
            DllStructGetPtr($tResource, "Body") + ($i - 1) * 16) ; every new structure is 16 bytes ahead

    ; RT_GROUP_ICON Body (see the simplcity I was talking about)
    $tGroupIconData = DllStructCreate("byte Width;" & _
            "byte Height;" & _
            "byte Colors;" & _
            "byte;" & _
            "word Planes;" & _
            "word BitPerPixel;" & _
            "dword BitmapSize;" & _
            "word OrdinalName;", _
            DllStructGetPtr($tIconGroupHeader, "Body") + ($i - 1) * 14) ; every new structure is 14 bytes ahead

    ; Copy from one structure to another
    DllStructSetData($tGroupIconData, "Width", DllStructGetData($tInputIconHeader, "Width"))
    DllStructSetData($tGroupIconData, "Height", DllStructGetData($tInputIconHeader, "Height"))
    DllStructSetData($tGroupIconData, "Colors", DllStructGetData($tInputIconHeader, "Colors"))
    DllStructSetData($tGroupIconData, 4, DllStructGetData($tInputIconHeader, 4)) ; this is reserved field (irrelevant actually)
    DllStructSetData($tGroupIconData, "Planes", DllStructGetData($tInputIconHeader, "Planes"))
    DllStructSetData($tGroupIconData, "BitPerPixel", DllStructGetData($tInputIconHeader, "BitPerPixel"))
    DllStructSetData($tGroupIconData, "BitmapSize", DllStructGetData($tInputIconHeader, "BitmapSize"))

    ; Set the name
    DllStructSetData($tGroupIconData, "OrdinalName", $iEnumIconName) ; That's the only difference between the two structures

    ; Write this new icon to PE file:
    DllCall("kernel32.dll", "bool", "UpdateResourceW", _
            "handle", $hHandle, _
            "int", 3, _ ; RT_ICON
            "int", $iEnumIconName, _
            "word", $iResLang, _
            "ptr", DllStructGetPtr($tResource) + DllStructGetData($tInputIconHeader, "BitmapOffset"), _ ; This is icon's data.
            "dword", DllStructGetData($tInputIconHeader, "BitmapSize")) ; and it's size
    ; ...checking errors here...

    ; New name for te icon
    $iEnumIconName += 1 ; This is usually done by incrementing the last one by one (can be any other scheme)
Next

; Finally write RT_GROUP_ICON:
DllCall("kernel32.dll", "bool", "UpdateResourceW", _
                "handle", $hHandle, _
                "int", 14, _ ; RT_GROUP_ICON
                "int", $iResName, _ ; Can be string too of course. In that case it's ..."wstr", StringUpper($sName), ...
                "word", $iResLang, _
                "ptr", DllStructGetPtr($tIconGroupHeader), _
                "dword", DllStructGetSize($tIconGroupHeader))
    ; ...checking errors here...

; End res modification procedure
DllCall("kernel32.dll", "bool", "EndUpdateResourceW", "handle", $hHandle, "int", 0)

; The End

That helps?

Thank you very much trancexx, you really save my day ;)

its awesome & extremely simple, now i got what the hell is "raw structure" and "ICONDIRENTRY idEntries[1]".

Again bundle of thanks for your kind help & this nice lesson.


73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites

Thank Jos. He taught me that.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Thank Jos. He taught me that.

Thanks Jos ;)


73 108 111 118 101 65 117 116 111 105 116

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0