Code: Select all
;
; Changing icon resources in executables (the NT-API way)
;
;
; NOTE:     Needs NT, 2000 or XP to work
;
;
;
; WARNING:  the following code is known to fail in certain cases
;           be sure to backup your data before using this!
;
;           
;
; (:t)raumatic - february 2005
;
#RT_GROUP_ICON = #RT_ICON + 11
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
Structure ICONDIRENTRYCOMMON
  bWidth.b        ; Width, in pixels, of the image
  bHeight.b       ; Height, in pixels, of the image
  bColorCount.b   ; Number of colors in image (0 if >=8bpp)
  bReserved.b     ; Reserved ( must be 0)
  wPlanes.w       ; Color Planes
  wBitCount.w     ; Bits per pixel
  dwBytesInRes.l  ; How many bytes in this resource?
EndStructure
;
Structure ICONDIRENTRY
  common.ICONDIRENTRYCOMMON
  dwImageOffset.l ; Where in the file is this image?
EndStructure
Structure ICONDIR
  idReserved.w              ; Reserved (must be 0)
  idType.w                  ; Resource Type (1 for icons)
  idCount.w                 ; How many images?
  idEntries.ICONDIRENTRY[0] ; An entry for each image (idCount of 'em)
EndStructure
;
Structure GRPICONDIR1ENTRY1
  common.ICONDIRENTRYCOMMON
  nId.w ; the ID
EndStructure
Structure GRPICONDIR1
  idReserved.w                  ; Reserved (must be 0)
  idType.w                      ; Resource type (1 for icons)
  idCount.w                     ; How many images?
  idEntries.GRPICONDIR1ENTRY1[0]  ; The entries for each image
EndStructure
;
; Change Icon-Resource in "exeFilename.s" with "iconFileName.s"
;
Procedure.l ChangeIcon(iconFileName.s, exeFileName.s)
  *icon.ICONDIR = AllocateMemory(SizeOf(ICONDIR))
  
  If ReadFile(0, iconFileName.s)
    ReadData(0, *icon, SizeOf(ICONDIR))
    
    *icon = ReAllocateMemory(*icon, SizeOf(ICONDIR) + (*icon\idCount*2) *SizeOf(ICONDIRENTRY))
    
    For i=0 To *icon\idCount-1
      FileSeek(0, 6+SizeOf(ICONDIRENTRY) * i)  ; SizeOf(ICONDIR) - SizeOf(ICONDIRENTRY) = 6
      ReadData(0, *icon\idEntries[i], SizeOf(ICONDIRENTRY) * (i+1))
    Next
    
    ;
    hInst.l = BeginUpdateResource_(exeFileName, #False)
    If hInst = 0
      retVal.l = #False
    Else
      
      ; CHANGE #RT_GROUP_ICON
      *iconGroup.GRPICONDIR1 = AllocateMemory(SizeOf(GRPICONDIR1) + 6 + SizeOf(GRPICONDIR1ENTRY1) * *icon\idCount)
      For i=0 To *icon\idCount-1
        CopyMemory(*icon\idEntries[i]\common, *iconGroup\idEntries[i]\common, SizeOf(ICONDIRENTRYCOMMON))
        *iconGroup\idEntries[i]\nId = (i+1)
      Next
      
      *iconGroup\idReserved = 0
      *iconGroup\idType     = 1
      *iconGroup\idCount    = *icon\idCount
      
      ;
      ; TODO: Error with bColorCount
      ;       Written value is always wrong!? (e.g. 1 instead of 16)
      ;
      
      retVal = UpdateResource_(hInst, #RT_GROUP_ICON, 1, #LANG_NEUTRAL, *iconGroup, 6+SizeOf(GRPICONDIR1ENTRY1)* *iconGroup\idCount)
      FreeMemory(*iconGroup) : *iconGroup = #Null
      
      
      ; CHANGE #RT_ICON
      For i = 0 To *icon\idCount-1
        ; get the desired icon from .ico file
        *resData = AllocateMemory(*icon\idEntries[i]\common\dwBytesInRes)
        FileSeek(0, *icon\idEntries[i]\dwImageOffset)
        ReadData(0, *resData, *icon\idEntries[i]\common\dwBytesInRes)
        
        retVal = UpdateResource_(hInst, #RT_ICON, (i+1), #LANG_NEUTRAL, *resData, *icon\idEntries[i]\common\dwBytesInRes)
      Next
      
      retVal = EndUpdateResource_(hInst, #False)
      
      FreeMemory(*resData) : *resData = #Null
    EndIf
    
    FreeMemory(*icon) : *icon = #Null
    CloseFile(0)
    
  Else
    retVal = #False
  EndIf
  
  ProcedureReturn retVal
EndProcedure




