/*
;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
;
;

translated to OxygenBasic  Charles E V Pegge 06/07/2022

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
*/

uses corewin

% RT_ICON 3
% RT_GROUP_ICON  14
% LANG_NEUTRAL 0x000 '0xc00


type ICONDIRENTRYCOMMON
  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?
end type
'12 bytes


type ICONDIRENTRY_A
  has ICONDIRENTRYCOMMON
  dword               dwImageOffset ' Where in the file is this image?
end type
'16 bytes


type ICONDIRENTRY_B
  has ICONDIRENTRYCOMMON
  'word                nId ' the ID
  'word                padding
  dword                nId 'dword to ensure upper word is zero
end type
'16 bytes


type ICONDIR
  word idReserved           ' Reserved (must be 0)
  word idType               ' Resource Type (1 for icons)
  word idCount              ' How many images?
end type
'6 bytes + ENTRYS FOLLOW IMMEDIATELY


function ViewIconData(string buf) as string
===========================================
indexbase 0
int i 'iterator
string pr 'return info
ICONDIR *id
ICONDIRENTRY_A *ie

@id = strptr(buf)
@ie = @id+6
pr="
Icon group header  
Reserved: " id.idReserved "
Type:     " id.idType "
Count:    " id.idCount "
Entry 1:
pixel width:      " ie.bWidth "
pixel height:     " ie.bHeight "
color count:      " ie.bColorCount "
reserved :        " ie.bReserved "
planes:           " ie.wPlanes "
bits per pixel:   " ie.wBitCount "
byte count:       " ie.dwBytesInRes "
file loc/ordinal: " ie.dwImageOffset "
"
return pr 
end function


function ViewIconFileData(string iconFileName) as string
========================================================
string buf = getfile(iconFileName)
string pr 'return info
if not buf
  pr="Icon file not found: " iconFileName
else
  pr=ViewIconData(buf)
endif
return pr
end function


'print ViewIconFileData "oxicon.ico"
'print ViewIconFileData "oxideicon.ico"


function ChangeIcon(int name, string iconFileName, exeFileName) as int
======================================================================
indexbase 0
int lang =  0x809 '0x809 LANG_UK  0x409 LANG_US, 0x0 LANG_NEUTRAL
int i 'iterator

string buf = getfile(iconFileName)
if len(buf)=0
  return 0
endif
' 
sys hRes = BeginUpdateResource(exeFileName, 0)
If hRes = 0
  return 0
endif
'
ICONDIR *icon
@icon = strptr(buf) 
int count = icon.idCount
'
' CHANGE EACH RT_ICON (3)
'------------------------
'
sys pbuf=strptr(buf)
sys pdat ' pointer to icon data
int ldat ' length of icon data
ICONDIRENTRY_A *ie
@ie=pbuf+6
for i = 0 to count-1
  ' get each icon from .ico file
  ldat = ie[i].dwBytesInRes
'print ldat ", " ie[i].dwImageOffset
  pdat = pbuf + ie[i].dwImageOffset
  function = UpdateResource( hRes , 3, i+1 , lang , pdat, ldat )
next

'CHANGE RT_GROUP_ICON (14)
'-------------------------
'
'copy of icon directory to be modified for group
string gbuf
gbuf=buf
ICONDIR *ig
@ig = strptr(gbuf)
ig.idReserved = 0
ig.idType     = 1
ig.idCount    = count
'
ICONDIRENTRY_B *ie
@ie=strptr(gbuf)+6
for i=0 to count-1
  ie[i].nId = i+1 'replacing ImageOffset
next
'   
int lg = 6 + SizeOf(ie) * count
function = UpdateResource( hRes, 14, name, lang , ig, lg )
gbuf=""
'
'
return EndUpdateResource(hRes, 0)
  
end function

ChangeIcon(1001,"OxIcon.ico","co2.exe")