Solved

Change icon of exe

Posted on 2001-08-29
23
3,205 Views
Last Modified: 2008-03-10
I have a number of Delphi programs that I made. I would like to change their icons so that I have a standard icon for all my programs. The problem is, I don't have the source code for some of my programs. Can anyone post source code for a program that can change the icon of an executable. Thanks!
0
Comment
Question by:DelFreak
  • 8
  • 6
  • 4
  • +4
23 Comments
 
LVL 4

Expert Comment

by:jeurk
ID: 6435706
Hi,
You may want to try the following component:
http://www.torry.net/vcl/graphics/icons/mbexeicon.zip
TExeIcon is a small component for Delphi . With TExeIcon you can modify the main icon of a EXE file. The component was designed to add this capability to AutoRun Multimedia Creator, a free program to create AutoRuns. TExeIcon features:
Modify icon of Win32 Exe Files
Compatible with all Programming Languages
The source is not included and it's for D4...

I know one expert here has such a program on his website but I can't find it anymore... and the search engine on E-E SUCKS so badly...
This is a question already asked many times...
The answer is here... SO if you wait a bit someone may give you the answer....

john.
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6438443
The freeware program reshacker makes this sort of thing easy

http://www.rpi.net.au/~ajohnson/resourcehacker/

0
 

Author Comment

by:DelFreak
ID: 6438970
It would be great if source code is posted. I would love to know how to do this. If anyone else could help, please do. Thanks!
0
 

Author Comment

by:DelFreak
ID: 6443696
I found source code that changes the icon of an exe. unfortunately, it's in C. Can anyone of you convert it to Delphi for me? Please! Thanks!
0
 
LVL 3

Expert Comment

by:Slavak
ID: 6448684
can you post the source?
0
 

Author Comment

by:DelFreak
ID: 6449412
Here's the source of IconWhack.h:

// My Constants
#define MAX_FILELEN      256
#define MAX_ICONSIZE 1600
#define WACK_SIG            0x4B434157L
#define NBITMAPS            8
#define NBUTTONS            4
#define BMPHEIGHT            64
#define BMPWIDTH            64
// Resource Constants
#define IDE1      1
#define IDE2      2
#define IDE3      3
#define IDE4      4
#define IDE5      5
#define IDE6      6
#define IDE7      7
#define IDE8      8
#define IDE9      9
#define IDE10      10
#define IDE11      11
#define IDE12      12
#define IDE13      13
//
#define CM_HELP                        203
#define CM_EXIT                        202
#define CM_WHACK                        201
#define CM_HELPABOUT                  206
#define CM_UNWHACK                  205
//
#define IDC_EDIT1                        101
#define IDC_EDIT2                        102
#define IDC_ICONLB                  104
#define IDC_BROWSEICO            106
#define IDC_BROWSEEXE            103
#define IDC_ICONEXE                  105
#define IDC_DLG2_BROWSE            102
#define IDC_HELP                        299
//
#define IDC_WACKFILE                  101
//
typedef struct _NAMEINFO {
      WORD rnOffset;
      WORD rnLength;
      WORD rnFlags;
      WORD rnID;
      WORD rnHandle;
      WORD rnUsage;
} NAMEINFO;

typedef struct _TYPEINFO {
      WORD       rtTypeID;
      WORD       rtResourceCount;
      DWORD      rtReserved;
} TYPEINFO;

typedef struct _ICONDIR {
      WORD idReserved;
      WORD idType;
      WORD idCount;
} ICONDIR;

typedef struct _ICONDIRENTRY {
      BYTE bWidth;
      BYTE bHeight;
      BYTE bColorCount;
      BYTE bReserved;
      WORD wPlanes;
      WORD wBitCount;
      DWORD dwBytesinRes;
      WORD wID;
} ICONDIRENTRY;

typedef struct _DISKICON {
      BYTE bWidth;
      BYTE bHeight;
      BYTE bColorCount;
      BYTE bRes1;
      WORD bRes2;
      WORD bRes3;
      DWORD dwBytesinRes;
      DWORD dwImageOffset;
} DISKICON;

typedef struct _IWICON {
      DWORD startico;
      DWORD starticodir;
      DWORD dwBytesinRes;
      BYTE bWidth;
      BYTE bHeight;
      BYTE bColorCount;
} IWICON;

typedef IWICON * PIWICON;
typedef IWICON NEAR * NPIWICON;
typedef IWICON FAR * LPIWICON;
//
// Function Prototypes
//
long FAR PASCAL _export WndProc(HWND,WORD,WPARAM,LPARAM);
BOOL FAR PASCAL _export DlgProc1(HWND,WORD,WPARAM,LPARAM);
BOOL FAR PASCAL _export DlgProc2(HWND,WORD,WPARAM,LPARAM);
BOOL FAR PASCAL _export DlgProcAbout(HWND,WORD,WPARAM,LPARAM);
int MyCommand(HWND,WPARAM);
void CenterDialog(HWND);
WORD WhackExe(const char *,const char *,WORD);
WORD UnWhackExe(const char *);
WORD SeekIcon(HFILE,PIWICON,WORD,BYTE,BYTE,BYTE);
int FileExists(const char *);
BOOL BrowseFile(HWND,WORD,char *);
void DrawBitmap(HDC,HBITMAP,WORD,WORD);
//


Hers' the source of IWHelp.h:

//
// Help Constants
//
#define HLP_DLG1                  400
#define HLP_DLG2                  401
#define HLP_DONATIONS      402
//


Here's the source of IconWhack.c:

//
// EXE File Icon Whacker
// By: Mitch Howard - 10/95
//
#include <windows.h>
#include <commdlg.h>
#include <mmsystem.h>
#include <shellapi.h>
#include <stdlib.h>
#include <mem.h>
#include <dir.h>

#include "iconwack.h"
#include "iwhelp.h"

const char *appname = "IconWhack";
const char *HelpFileName = "ICONWACK.HLP";
const char *IniName = "ICONWACK.INI";
int SoundFlag;
HANDLE hInst;
HICON hicon;
HBITMAP hBmp[NBITMAPS];
HWND hwndBtn[NBUTTONS];

#pragma argsused
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
      WORD tx,ty;
      MSG msg;
      WNDCLASS wc;
      HWND hwnd;

      hInst = hInstance;  // Store Instance in Global variable
      hicon = LoadIcon(hInstance,"ICONWACK_ICON");  // Store Icon in Global var
      hBmp[0] = LoadBitmap(hInstance,"WACK_UP");
      hBmp[1] = LoadBitmap(hInstance,"WACK_DOWN");
      hBmp[2] = LoadBitmap(hInstance,"UNWACK_UP");
      hBmp[3] = LoadBitmap(hInstance,"UNWACK_DOWN");
      hBmp[4] = LoadBitmap(hInstance,"HELP_UP");
      hBmp[5] = LoadBitmap(hInstance,"HELP_DOWN");
      hBmp[6] = LoadBitmap(hInstance,"EXIT_UP");
      hBmp[7] = LoadBitmap(hInstance,"EXIT_DOWN");

      SoundFlag = FALSE;
      if (waveOutGetNumDevs() > 0)
            SoundFlag = TRUE;

      if (!hPrevInstance) {
            wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
            wc.lpfnWndProc = (WNDPROC) WndProc;
            wc.cbClsExtra = 0;
            wc.cbWndExtra = 0;
            wc.hInstance = hInstance;
            wc.hIcon = hicon;
            wc.hCursor = LoadCursor(NULL,IDC_ARROW);
            wc.hbrBackground = GetStockObject(WHITE_BRUSH);
            wc.lpszMenuName = "ICONWACK_MENU";
            wc.lpszClassName = appname;
            RegisterClass(&wc);
      }
      tx = GetSystemMetrics(SM_CXFRAME)*2 + (BMPHEIGHT * NBUTTONS) + NBUTTONS;
      ty = GetSystemMetrics(SM_CYFRAME)*2 + GetSystemMetrics(SM_CYMENU);
      ty += GetSystemMetrics(SM_CYCAPTION) + BMPHEIGHT + 1;
      hwnd = CreateWindow(appname,appname, WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT, CW_USEDEFAULT,
                                          tx, ty, NULL, NULL, hInstance, NULL);
      CenterDialog(hwnd);
      ShowWindow(hwnd,nCmdShow);
      UpdateWindow(hwnd);

      while (GetMessage(&msg,NULL,0,0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

      return msg.wParam;
}

long FAR PASCAL WndProc(HWND hwnd, WORD message, WPARAM wParam, LPARAM lParam)
{
      WORD z;
      LPMEASUREITEMSTRUCT lpMeasure;
      LPDRAWITEMSTRUCT lpDraw;

      switch (message) {
            case WM_CREATE:
                  for (z = 0; z < NBUTTONS; z++) {
                        hwndBtn[z] = CreateWindow("button","",BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_BORDER,
                                                                        z * BMPWIDTH + 2,1,BMPWIDTH,BMPHEIGHT,hwnd,z+1,hInst,NULL);
                  }
                  return 0;
            case WM_DESTROY:
                  WinHelp(hwnd,HelpFileName,HELP_QUIT,0L);
                  for (z = 0; z < NBITMAPS; z++) {
                        if (hBmp[z])
                              DeleteObject(hBmp[z]);
                  }
                  PostQuitMessage(0);
                  return 0;
            case WM_MEASUREITEM:
                  lpMeasure = (LPMEASUREITEMSTRUCT) lParam;
                  lpMeasure->CtlType = ODT_BUTTON;
                  for (z = 0; z < NBUTTONS; z++) {
                        if (wParam == hwndBtn[z]) {
                              lpMeasure->CtlID = z+1;
                              break;
                        }
                  }
                  lpMeasure->itemID = 0;
                  lpMeasure->itemWidth = BMPWIDTH;
                  lpMeasure->itemHeight = BMPHEIGHT;
                  lpMeasure->itemData = 0;
                  return 0;
            case WM_DRAWITEM:
                  lpDraw = (DRAWITEMSTRUCT FAR*) lParam;
                  if ((lpDraw->itemAction == ODA_DRAWENTIRE) || (lpDraw->itemAction == ODA_SELECT)) {
                        for (z = 0; z < NBUTTONS; z++) {
                              if (lpDraw->CtlID == z+1) {
                                    if (lpDraw->itemState & ODS_SELECTED)
                                          DrawBitmap(lpDraw->hDC,hBmp[z+z+1],lpDraw->rcItem.left,lpDraw->rcItem.top);
                                    else
                                          DrawBitmap(lpDraw->hDC,hBmp[z+z],lpDraw->rcItem.left,lpDraw->rcItem.top);
                              }
                        }
                  }
                  return 0;
            case WM_COMMAND:
                  if (LOWORD(lParam)) {            // From a Control
                        switch (HIWORD(lParam)) {
                              case BN_CLICKED:
                                    switch (wParam) {
                                          case 1:
                                                PostMessage(hwnd,WM_COMMAND,CM_WHACK,0L);
                                                break;
                                          case 2:
                                                PostMessage(hwnd,WM_COMMAND,CM_UNWHACK,0L);
                                                break;
                                          case 3:
                                                PostMessage(hwnd,WM_COMMAND,CM_HELP,0L);
                                                break;
                                          case 4:
                                                PostMessage(hwnd,WM_COMMAND,CM_EXIT,0L);
                                                break;
                                    }
                        }
                        return 0;
                  }
                  else {
                        if (MyCommand(hwnd,wParam) == 0)
                              return 0;
                  }
                  break;
      }
      return DefWindowProc(hwnd,message,wParam,lParam);
}

int MyCommand(HWND hwnd,WPARAM wParam)
{
//
// Handle WM_COMMAND messages
// Returns TRUE if the message was not handled
//
      DLGPROC dlgproc;

      switch (wParam) {
            case CM_WHACK:
                  dlgproc = MakeProcInstance(DlgProc1, hInst);
                  DialogBox(hInst,"ICONWACK_DLG1",hwnd,dlgproc);
                  FreeProcInstance(dlgproc);
                  break;
            case CM_UNWHACK:
                  dlgproc = MakeProcInstance(DlgProc2, hInst);
                  DialogBox(hInst,"ICONWACK_DLG2",hwnd,dlgproc);
                  FreeProcInstance(dlgproc);
                  break;
            case CM_HELPABOUT:
                  dlgproc = MakeProcInstance(DlgProcAbout, hInst);
                  DialogBox(hInst,"ICONWACK_ABOUT",hwnd,dlgproc);
                  FreeProcInstance(dlgproc);
                  break;
            case CM_HELP:
                  WinHelp(hwnd,HelpFileName,HELP_CONTENTS,0L);
                  break;
            case CM_EXIT:
                  SendMessage(hwnd,WM_CLOSE,0,0L);
                  break;
            default:
                  return TRUE;
      }
      return FALSE;
}

BOOL FAR PASCAL _export DlgProc1(HWND hDlg,WORD message,WPARAM wParam,LPARAM lParam)
{
      char exename[MAX_FILELEN];
      char iconame[MAX_FILELEN];
      static char temp[MAX_FILELEN+20];
      int oldmode, iconum;
      HWND lbwh, icwh;
      HICON hic, nicons;
      WORD z, iw;
      UINT inum;
      HDC hdc;
      HPEN oldpen;
      LPMEASUREITEMSTRUCT lpMeasure;
      LPDRAWITEMSTRUCT lpDraw;
      RECT r;

      switch (message) {
            case WM_INITDIALOG:
                  CenterDialog(hDlg);
                  SendDlgItemMessage(hDlg,IDC_EDIT1,EM_LIMITTEXT,MAX_FILELEN,0L);
                  SendDlgItemMessage(hDlg,IDC_EDIT2,EM_LIMITTEXT,MAX_FILELEN,0L);
                  GetPrivateProfileString("WHACKDLG","DEST","",exename,MAX_FILELEN,IniName);
                  SetDlgItemText(hDlg,IDC_EDIT1,exename);
                  icwh = GetDlgItem(hDlg,IDC_ICONEXE);
                  if (FileExists(exename)) {
                        hic = ExtractIcon(hInst,exename,0);
                        if (hic != NULL) {
                              SendDlgItemMessage(hDlg,IDC_ICONEXE,STM_SETICON,(WPARAM) hic,0L);
                              InvalidateRect(icwh,NULL,TRUE);
                              UpdateWindow(icwh);
                        }
                        SetFocus(GetDlgItem(hDlg,IDC_EDIT2));
                  }
                  GetPrivateProfileString("WHACKDLG","SOURCE","",iconame,MAX_FILELEN,IniName);
                  SetDlgItemText(hDlg,IDC_EDIT2,iconame);
                  if (FileExists(iconame)) {
                        lbwh = GetDlgItem(hDlg,IDC_ICONLB);
                        nicons = ExtractIcon(hInst,iconame,-1);
                        if (nicons != NULL) {
                              SendMessage(lbwh,LB_RESETCONTENT,0,0L);
                              for (z = 0; z < nicons; z++)
                                    SendMessage(lbwh,LB_ADDSTRING,0,z);
                              SendMessage(lbwh,LB_SETCURSEL,0,0);
                        }
                        SetFocus(GetDlgItem(hDlg,IDC_ICONLB));
                  }
                  return TRUE;
            case WM_MEASUREITEM:
                  lpMeasure = (LPMEASUREITEMSTRUCT) lParam;
                  lpMeasure->CtlType = ODT_LISTBOX;
                  lpMeasure->CtlID = IDC_ICONLB;
                  lpMeasure->itemID = 0;
                  lpMeasure->itemWidth = GetSystemMetrics(SM_CXICON) + 2;
                  lpMeasure->itemHeight = GetSystemMetrics(SM_CYICON) + 2;
                  lpMeasure->itemData = 0;
                  return TRUE;
            case WM_DRAWITEM:
                  lpDraw = (DRAWITEMSTRUCT FAR*) lParam;
                  hdc = lpDraw->hDC;
                  r = lpDraw->rcItem;
                  inum = (UINT) lpDraw->itemData;
                  switch (lpDraw->itemAction) {
                        case ODA_DRAWENTIRE:
                        case ODA_SELECT:
                              GetDlgItemText(hDlg,IDC_EDIT2,iconame,MAX_FILELEN);
                              hic = ExtractIcon(hInst,iconame,inum);
                              if (hic != NULL) {
                                    DrawIcon(hdc,r.left+2,r.top+2,hic);
                                    DestroyIcon(hic);
                              }
                              return TRUE;
                        case ODA_FOCUS:
                              oldmode = SetBkMode(hdc,TRANSPARENT);
                              if (lpDraw->itemState & ODS_FOCUS)
                                    oldpen = SelectObject(hdc,GetStockObject(BLACK_PEN));
                              else
                                    oldpen = SelectObject(hdc,GetStockObject(WHITE_PEN));
                              MoveTo(hdc,r.left,r.top);
                              iw = GetSystemMetrics(SM_CXICON);
                              LineTo(hdc,r.left+iw+3,r.top);
                              LineTo(hdc,r.left+iw+3,r.bottom+1);
                              LineTo(hdc,r.left,r.bottom+1);
                              LineTo(hdc,r.left,r.top);
                              SelectObject(hdc,oldpen);
                              SetBkMode(hdc,oldmode);
                              return TRUE;
                  }
                  return (FALSE);
            case WM_COMMAND:
                  switch (wParam) {
                        case IDC_HELP:
                              WinHelp(hDlg,HelpFileName,HELP_CONTEXT,HLP_DLG1);
                              return TRUE;
                        case IDC_BROWSEEXE:
                              if (BrowseFile(hDlg,0,exename)) {
                                    SetDlgItemText(hDlg,IDC_EDIT1,exename);
                                    icwh = GetDlgItem(hDlg,IDC_ICONEXE);
                                    if (FileExists(exename)) {
                                          hic = ExtractIcon(hInst,exename,0);
                                          if (hic == NULL)
                                                MessageBox(hDlg,"No icons in this EXE file.","Error",MB_OK);
                                          else {
                                                SendDlgItemMessage(hDlg,IDC_ICONEXE,STM_SETICON,(WPARAM) hic,0L);
                                                InvalidateRect(icwh,NULL,TRUE);
                                                UpdateWindow(icwh);
                                          }
                                          SetFocus(GetDlgItem(hDlg,IDC_EDIT2));
                                    }
                                    else
                                          SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
                              }
                              else
                                    SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
//                              SendDlgItemMessage(hDlg, IDC_BROWSEEXE, BM_SETSTATE, FALSE, 0L);
                              return TRUE;
                        case IDC_BROWSEICO:
                              if (BrowseFile(hDlg,1,iconame)) {
                                    lbwh = GetDlgItem(hDlg,IDC_ICONLB);
                                    if (FileExists(iconame)) {
                                          nicons = ExtractIcon(hInst,iconame,-1);
                                          if (nicons == NULL)
                                                MessageBox(hDlg,"No icons in this file.","Error",MB_OK);
                                          else {
                                                SetDlgItemText(hDlg,IDC_EDIT2,iconame);
                                                SendMessage(lbwh,LB_RESETCONTENT,0,0L);
                                                for (z = 0; z < nicons; z++)
                                                      SendMessage(lbwh,LB_ADDSTRING,0,z);
                                                SendMessage(lbwh,LB_SETCURSEL,0,0);
                                          }
                                          SetFocus(GetDlgItem(hDlg,IDC_ICONLB));
                                    }
                                    else
                                          SetFocus(GetDlgItem(hDlg,IDC_EDIT2));
                              }
                              else
                                    SetFocus(GetDlgItem(hDlg,IDC_EDIT2));
                              return TRUE;
                        case IDC_EDIT1:
                              switch (HIWORD(lParam)) {
                                    case EN_KILLFOCUS:
                                          GetDlgItemText(hDlg,IDC_EDIT1,exename,MAX_FILELEN);
                                          if (lstrcmp(exename,temp)) {
                                                icwh = GetDlgItem(hDlg,IDC_ICONEXE);
                                                if (FileExists(exename)) {
                                                      hic = ExtractIcon(hInst,exename,0);
                                                      if (hic == NULL)
                                                            MessageBox(hDlg,"No icons in this EXE file.","Error",MB_OK);
                                                      else {
                                                            SendDlgItemMessage(hDlg,IDC_ICONEXE,STM_SETICON,(WPARAM) hic,0L);
                                                            InvalidateRect(icwh,NULL,TRUE);
                                                            UpdateWindow(icwh);
                                                      }
                                                }
                                          }
                                          break;
                                    case EN_SETFOCUS:
                                          GetDlgItemText(hDlg,IDC_EDIT1,temp,MAX_FILELEN);
                                          break;
                              }
                              return TRUE;
                        case IDC_EDIT2:
                              switch (HIWORD(lParam)) {
                                    case EN_KILLFOCUS:
                                          GetDlgItemText(hDlg,IDC_EDIT2,iconame,MAX_FILELEN);
                                          if (lstrcmp(iconame,temp)) {
                                                lbwh = GetDlgItem(hDlg,IDC_ICONLB);
                                                if (FileExists(iconame)) {
                                                      nicons = ExtractIcon(hInst,iconame,-1);
                                                      if (nicons == NULL)
                                                            MessageBox(hDlg,"No icons in this file.","Error",MB_OK);
                                                      else {
                                                            SendMessage(lbwh,LB_RESETCONTENT,0,0L);
                                                            for (z = 0; z < nicons; z++)
                                                                  SendMessage(lbwh,LB_ADDSTRING,0,z);
                                                            SendMessage(lbwh,LB_SETCURSEL,0,0);
                                                      }
                                                }
                                                else
                                                      SendMessage(lbwh,LB_RESETCONTENT,0,0L);
                                          }
                                          break;
                                    case EN_SETFOCUS:
                                          GetDlgItemText(hDlg,IDC_EDIT2,temp,MAX_FILELEN);
                                          break;
                              }
                              return TRUE;
                        case IDOK:
                              GetDlgItemText(hDlg,IDC_EDIT1,exename,MAX_FILELEN);
                              GetDlgItemText(hDlg,IDC_EDIT2,iconame,MAX_FILELEN);
                              if (FileExists(exename)) {
                                    if (FileExists(iconame)) {
                                          WritePrivateProfileString("WHACKDLG","DEST",exename,IniName);
                                          WritePrivateProfileString("WHACKDLG","SOURCE",iconame,IniName);
                                          WritePrivateProfileString(NULL,NULL,NULL,IniName);  // Flush INI file
                                          iconum = (int) SendDlgItemMessage(hDlg,IDC_ICONLB,LB_GETCURSEL,0,0L);
                                          if (iconum >= 0) {
                                                z = WhackExe(exename,iconame,iconum);
                                                if (z > 0) {
                                                      LoadString(hInst,z,temp,60);
                                                      MessageBox(hDlg,temp,"Msg",MB_OK);
                                                }
                                                else {
                                                      wsprintf(temp,"Icon in %s has been Wacked.",(LPSTR) exename);
                                                      MessageBox(hDlg,temp,"Successful Whack",MB_OK);
                                                }
                                                EndDialog(hDlg,0);
                                          }
                                    }
                                    else {
                                          MessageBox(hDlg,"You must specify an valid ICO/EXE/DLL file.","Error",MB_OK);
                                          SetFocus(GetDlgItem(hDlg,IDC_EDIT2));
                                    }
                              }
                              else {
                                    MessageBox(hDlg,"You must specify an existing .EXE file.","Error",MB_OK);
                                    SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
                              }
                              return TRUE;
                        case IDCANCEL:
                              EndDialog(hDlg,0);
                              return TRUE;
                  }
                  break;
      }
      return FALSE;
}

#pragma argsused
BOOL FAR PASCAL _export DlgProc2(HWND hDlg,WORD message,WPARAM wParam,LPARAM lParam)
{
      char wackname[MAX_FILELEN];

      switch (message) {
            case WM_INITDIALOG:
                  CenterDialog(hDlg);
                  SendDlgItemMessage(hDlg,IDC_WACKFILE,EM_LIMITTEXT,MAX_FILELEN,0L);
                  GetPrivateProfileString("UNWHACKDLG","FILE","",wackname,MAX_FILELEN,IniName);
                  SetDlgItemText(hDlg,IDC_WACKFILE,wackname);
                  return TRUE;
            case WM_COMMAND:
                  switch (wParam) {
                        case IDC_HELP:
                              WinHelp(hDlg,HelpFileName,HELP_CONTEXT,HLP_DLG2);
                              return TRUE;
                        case IDC_DLG2_BROWSE:
                              if (BrowseFile(hDlg,2,wackname))
                                    SetDlgItemText(hDlg,IDC_WACKFILE,wackname);
                              SetFocus(GetDlgItem(hDlg,IDC_WACKFILE));
                              return TRUE;
                        case IDOK:
                              GetDlgItemText(hDlg,IDC_WACKFILE,wackname,MAX_FILELEN);
                              if (FileExists(wackname)) {
                                    WritePrivateProfileString("UNWHACKDLG","FILE",wackname,IniName);
                                    WritePrivateProfileString(NULL,NULL,NULL,IniName);  // Flush INI file
                                    if (UnWhackExe(wackname))
                                          MessageBox(hDlg,"Cannot restore Icon in EXE","Error",MB_OK);
                                    else
                                          MessageBox(hDlg,"Original Icon restored.","Successful UnWhack",MB_OK);
                                    EndDialog(hDlg,0);
                              }
                              else {
                                    MessageBox(hDlg,"You must specify a valid .WCK file.","Error",MB_OK);
                                    SetFocus(GetDlgItem(hDlg,IDC_WACKFILE));
                              }
                              return TRUE;
                        case IDCANCEL:
                              EndDialog(hDlg,0);
                              return TRUE;
                  }
                  break;
      }
      return FALSE;
}

#pragma argsused
BOOL FAR PASCAL _export DlgProcAbout(HWND hDlg,WORD message,WPARAM wParam,LPARAM lParam)
{
      switch (message) {
            case WM_INITDIALOG:
                  CenterDialog(hDlg);
                  return TRUE;
            case WM_COMMAND:
                  switch (wParam) {
                        case IDC_HELP:
                              SetFocus(GetDlgItem(hDlg,IDOK));
                              WinHelp(hDlg,HelpFileName,HELP_CONTEXT,HLP_DONATIONS);
                              return TRUE;
                        case IDOK:
                        case IDCANCEL:
                              EndDialog(hDlg,0);
                              return TRUE;
                  }
                  break;
      }
      return FALSE;
}

void CenterDialog(HWND hwnd)
{
      WORD ww, wh;
      RECT rect, desktop;

      GetWindowRect(GetDesktopWindow(),&desktop);
      GetWindowRect(hwnd,&rect);
      ww = rect.right - rect.left;
      wh = rect.bottom - rect.top;
      MoveWindow(hwnd,(desktop.right-ww)/2,(desktop.bottom-wh)/2,ww,wh,TRUE);
      return;
}

int FileExists(const char *fname)
{
//
// Checks to see if a file exists
// Returns TRUE if it is found
//
      struct ffblk dirinfo;

      if (findfirst(fname,&dirinfo,0))
            return FALSE;
      return TRUE;
}

WORD SeekIcon(HFILE exefile,PIWICON piwicon,WORD iconum,BYTE cc,BYTE bw,BYTE bh)
{
//
// Seeks to a given Icon within an EXE or DLL
// Upon successful completion, the IWICON structure
// will be filled in with all relevant information.
//
      WORD sig, head, rshift, z, offset, icmatch, TrueIconCount, tempcount;
      LONG coffset, newpos, savepos;
      TYPEINFO rti;
      NAMEINFO nameinfo;
      ICONDIR icondir;
      ICONDIRENTRY icondirentry;

      memset(piwicon,0,sizeof(IWICON));

      if (_llseek(exefile,0L,0) == -1)
            return 3;
      if (_lread(exefile,&sig,sizeof(WORD)) != sizeof(WORD))
            return 3;
// Check DOS EXE signature
      if (sig != 0x5A4D)
            return 4;
      if (_llseek(exefile,0x18,0) == -1)
            return 3;
      if (_lread(exefile,&head,sizeof(WORD)) != sizeof(WORD))
            return 3;
      if (head < 0x40)
            return 4;            // Not an EXE that we can use
      if (_llseek(exefile,0x3CL,0) == -1)
            return 3;
      if (_lread(exefile,&head,sizeof(WORD)) != sizeof(WORD))
            return 3;
      if (_llseek(exefile,(LONG) head,0) == -1)
            return 3;
      if (_lread(exefile,&sig,sizeof(WORD)) != sizeof(WORD))
            return 3;
// Check Win EXE signature
      if (sig != 0x454E)
            return 6;
      if (_llseek(exefile,(LONG) head + 0x24L,0) == -1)
            return 3;
      if (_lread(exefile,&offset,sizeof(WORD)) != sizeof(WORD))
            return 3;
// Move to start of Resource Table
      if (_llseek(exefile,(LONG) offset + (LONG) head,0) == -1)
            return 3;
      if (_lread(exefile,&z,sizeof(WORD)) != sizeof(WORD))
            return 3;
      rshift = 1;
      if (z) {
            while (z-- > 0)
                  rshift *= 2;
      }
// Read each TYPEINFO structure in Resource Table
// looking for 0x0E (RT_GROUP_ICON) first and then 0x03 (RT_ICON)
      icmatch = 0;
      do {
            if (_lread(exefile,&rti,sizeof(TYPEINFO)) != sizeof(TYPEINFO))
                  return 3;
            if ((rti.rtTypeID == 0) || (rti.rtReserved))
                  break;
            coffset = _llseek(exefile,0L,1);      // Save offset
            if ((rti.rtTypeID & 0x7FFF) == 14) {
                  if (rti.rtResourceCount <= iconum)
                        return 5;
                  TrueIconCount = 0;
                  for (z = 0; z <= iconum; z++) {
                        if (_lread(exefile,&nameinfo,sizeof(NAMEINFO)) != sizeof(NAMEINFO))
                              return 3;
                        savepos = _llseek(exefile,0L,1);      // Save current offset
                        newpos = (DWORD) rshift * (DWORD) nameinfo.rnOffset + 4L;
                        if (_llseek(exefile,newpos,0) == -1)
                              return 3;
                        if (_lread(exefile,&tempcount,sizeof(WORD)) != sizeof(WORD))
                              return 3;
                        if (z < iconum)
                              TrueIconCount += tempcount;
                        if (_llseek(exefile,savepos,0) == -1)
                              return 3;
                  }
                  piwicon->starticodir = newpos - 4L;
                  if (_llseek(exefile,piwicon->starticodir,0) == -1)
                        return 3;
                  if (_lread(exefile,&icondir,sizeof(ICONDIR)) != sizeof(ICONDIR))
                        return 3;
                  for (z = 1; z <= icondir.idCount; z++) {
                        if (_lread(exefile,&icondirentry,sizeof(ICONDIRENTRY)) != sizeof(ICONDIRENTRY))
                              return 3;
                        if ((icondirentry.bWidth == bw) && (icondirentry.bHeight == bh) && (icondirentry.bColorCount == cc)) {
                              icmatch = z;
                              break;
                        }
                  }
                  if (icondirentry.dwBytesinRes >= MAX_ICONSIZE)
                        return 10;
                  piwicon->bWidth = icondirentry.bWidth;
                  piwicon->bHeight = icondirentry.bHeight;
                  piwicon->bColorCount = icondirentry.bColorCount;
                  piwicon->dwBytesinRes = icondirentry.dwBytesinRes;
                  break;
            }
            if (_llseek(exefile,coffset + (LONG) rti.rtResourceCount * (LONG) sizeof(NAMEINFO),0) == -1)
                  return 3;
      } while (piwicon->starticodir == 0L);
      if (piwicon->starticodir == 0L)
            return 7;            // Cannot find Icons
//
// Look back thru Resource Table for the RT_ICON (0x03) Resource ID
//
      if (_llseek(exefile,(LONG) offset + (LONG) head + (LONG) sizeof(WORD),0) == -1)
            return 3;
      do {
            if (_lread(exefile,&rti,sizeof(TYPEINFO)) != sizeof(TYPEINFO))
                  return 3;
            if ((rti.rtTypeID == 0) || (rti.rtReserved))
                  break;
            coffset = _llseek(exefile,0L,1);      // Save offset
            if ((rti.rtTypeID & 0x7FFF) == 3) {
                  if (rti.rtResourceCount <= TrueIconCount)
                        return 5;
                  if (_llseek(exefile,(LONG) TrueIconCount * (LONG) sizeof(NAMEINFO),1) == -1)
                        return 3;
                  if (_lread(exefile,&nameinfo,sizeof(NAMEINFO)) != sizeof(NAMEINFO))
                        return 3;
                  if ((icmatch > 1) && (rti.rtResourceCount > 1)) {
                        if (icmatch > rti.rtResourceCount)
                              return 11;
                        for (z = 2; z <= icmatch; z++) {
                              if (_lread(exefile,&nameinfo,sizeof(NAMEINFO)) != sizeof(NAMEINFO))
                                    return 3;
                        }
                  }
                  piwicon->startico = (DWORD) rshift * (DWORD) nameinfo.rnOffset;
                  break;
            }
            if (_llseek(exefile,coffset + (LONG) rti.rtResourceCount * (LONG) sizeof(NAMEINFO),0) == -1)
                  return 3;
      } while (piwicon->startico == 0L);
      if (piwicon->startico == 0L)
            return 7;            // Cannot find Icons
      return 0;
}

WORD WhackExe(const char *exename,const char *iconame,WORD iconum)
{
      HFILE exefile, icofile, backupfile;
      char backupname[MAX_FILELEN];
      char tempname[MAX_FILELEN];
      char iconbuf[MAX_ICONSIZE];
      char savebuf[MAX_ICONSIZE];
      BYTE iw, ih, ic;
      WORD sig, err, z;
      DWORD wacksig;
      ICONDIR diskicondir;
      DISKICON diskicon;
      IWICON iwicon, tempiwicon;
      HDC hdc;

      if (SoundFlag)
//               if (FileExists("WHACK.WAV"))
                  sndPlaySound("WHACK.WAV",SND_ASYNC | SND_NODEFAULT);
      z = lstrlen(exename);
      if (z < 3)
            return 4;
      if (*(exename+z-1) != 'E')
            return 4;
      if (*(exename+z-2) != 'X')
            return 4;
      if (*(exename+z-3) != 'E')
            return 4;
      icofile = _lopen(iconame, READ);
      if (icofile == -1)
            return 1;            // Cannot open ICO file
      sig = 0;
      if (_lread(icofile,&sig,sizeof(WORD)) != sizeof(WORD))
            sig = 0;
      iw = (BYTE) GetSystemMetrics(SM_CXICON);
      ih = (BYTE) GetSystemMetrics(SM_CYICON);
      ic = 2;      // Minimum Icon colors
      hdc = GetDC(NULL);
      if (GetDeviceCaps(hdc,SIZEPALETTE) > 16)
            ic = 16;      // Max icon colors
      ReleaseDC(NULL, hdc);
      if (sig == 0x5A4D) {       // An EXE or DLL, so extract ICON data
            err = SeekIcon(icofile,&tempiwicon,iconum,ic,iw,ih);
            if (err) {
                  _lclose(icofile);
                  return err;
            }
            if (_llseek(icofile,tempiwicon.startico,0) == -1) {
                  _lclose(icofile);
                  return 3;
            }
            if (_lread(icofile,&iconbuf[0],(WORD) tempiwicon.dwBytesinRes) != (WORD) tempiwicon.dwBytesinRes) {
                  _lclose(icofile);
                  return 3;
            }
            diskicondir.idReserved = 0;
            diskicondir.idType = 1;
            diskicondir.idCount = 1;
            memset(&diskicon,0,sizeof(DISKICON));
            diskicon.bWidth = tempiwicon.bWidth;
            diskicon.bHeight = tempiwicon.bHeight;
            diskicon.bColorCount = tempiwicon.bColorCount;
            diskicon.dwBytesinRes = tempiwicon.dwBytesinRes;
            diskicon.dwImageOffset = sizeof(DISKICON) + sizeof(ICONDIR);
      }
      else {
            _llseek(icofile,0L,0);
            if (_lread(icofile,&diskicondir,sizeof(ICONDIR)) != sizeof(ICONDIR)) {
                  _lclose(icofile);
                  return 3;
            }
            for (z = 1; z <= diskicondir.idCount; z++) {
                  if (_lread(icofile,&diskicon,sizeof(DISKICON)) != sizeof(DISKICON)) {
                        _lclose(icofile);
                        return 3;
                  }
                  if ((diskicon.bColorCount == ic) && (diskicon.bWidth == iw) && (diskicon.bHeight == ih))
                        break;
            }
            if (_llseek(icofile,diskicon.dwImageOffset,0) == -1) {
                  _lclose(icofile);
                  return 3;
            }
            if (_lread(icofile,&iconbuf[0],(WORD) diskicon.dwBytesinRes) != (WORD) diskicon.dwBytesinRes) {
                  _lclose(icofile);
                  return 3;
            }
      }
      _lclose(icofile);
// All Icon data is ready, so now write to EXE
      exefile = _lopen(exename, READ_WRITE);
      if (exefile == -1)
            return 2;
      err = SeekIcon(exefile,&iwicon,0,diskicon.bColorCount,diskicon.bWidth,diskicon.bHeight);
      if (err) {
            _lclose(exefile);
            return err;
      }
// Check Icon compatibility (size, colors, height, width)
      err = 0;
      if ((diskicon.bWidth != iwicon.bWidth) || (diskicon.bHeight != iwicon.bHeight))
            err = 13;
      if (diskicon.bColorCount != iwicon.bColorCount)
            err = 12;
      if (diskicon.dwBytesinRes != iwicon.dwBytesinRes)
            err = 11;
      if (err == 0) {
            if (_llseek(exefile,iwicon.startico,0) != -1) {
                  // Save old data
                  if (_lread(exefile,&savebuf[0],(WORD) diskicon.dwBytesinRes) == (WORD) diskicon.dwBytesinRes) {
                        if (_llseek(exefile,iwicon.startico,0) != -1) {
                              if (_lwrite(exefile,&iconbuf[0],(WORD) diskicon.dwBytesinRes) != (WORD) diskicon.dwBytesinRes)
                                    err = 3;
                        }
                        else
                              err = 3;
                  }
                  else
                        err = 3;
            }
            else
                  err = 3;
      }
      _lclose(exefile);
      if (err)
            return err;
// Make backup file so that Icon change can be reversed
      lstrcpy(backupname,exename);
      memset(tempname,0,MAX_FILELEN);
      lstrcpy(tempname,exename);
      z = lstrlen(backupname);
      backupname[z-1] = 'K';
      backupname[z-2] = 'C';
      backupname[z-3] = 'W';
      if (FileExists(backupname) == FALSE) {
            backupfile = _lcreat(backupname, 0);
            if (backupfile != -1) {
                  wacksig = WACK_SIG;
                  if (_lwrite(backupfile,&wacksig,sizeof(DWORD)) == sizeof(DWORD)) {
                        if (_lwrite(backupfile,&tempname[0],MAX_FILELEN) == MAX_FILELEN) {
                              if (_lwrite(backupfile,&diskicon.dwBytesinRes,sizeof(DWORD)) == sizeof(DWORD)) {
                                    if (_lwrite(backupfile,&iwicon.startico,sizeof(DWORD)) == sizeof(DWORD))
                                          _lwrite(exefile,&savebuf[0],(WORD) diskicon.dwBytesinRes);
                              }
                        }
                  }
                  _lclose(backupfile);
            }
      }
      return 0;
}

WORD UnWhackExe(const char *wackname)
{
      HFILE wackfile, exefile;
      DWORD wacksig, icosize, icostart;
      char exename[MAX_FILELEN];
      char iconbuf[MAX_ICONSIZE];

      if (SoundFlag)
            sndPlaySound("UNWHACK.WAV",SND_ASYNC | SND_NODEFAULT);
      wackfile = _lopen(wackname,READ);
      if (wackfile == -1)
            return 2;
      if (_lread(wackfile,&wacksig,sizeof(DWORD)) != sizeof(DWORD)) {
            _lclose(wackfile);
            return 3;
      }
      if (wacksig != WACK_SIG) {
            _lclose(wackfile);
            return 4;
      }
      if (_lread(wackfile,exename,MAX_FILELEN) != MAX_FILELEN) {
            _lclose(wackfile);
            return 3;
      }
      if (_lread(wackfile,&icosize,sizeof(DWORD)) != sizeof(DWORD)) {
            _lclose(wackfile);
            return 3;
      }
      if (_lread(wackfile,&icostart,sizeof(DWORD)) != sizeof(DWORD)) {
            _lclose(wackfile);
            return 3;
      }

      if (_lread(wackfile,&iconbuf[0],(WORD) icosize) != (WORD) icosize) {
            _lclose(wackfile);
            return 3;
      }
      _lclose(wackfile);

      if (FileExists(exename) == FALSE)
            return 2;

      exefile = _lopen(exename, READ_WRITE);
      if (exefile == -1)
            return 2;

      if (_llseek(exefile,icostart,0) == -1) {
            _lclose(exefile);
            return 3;
      }
      if (_lwrite(exefile,&iconbuf[0],(WORD) icosize) != (WORD) icosize) {
            _lclose(exefile);
            return 3;
      }
      _lclose(exefile);
      return 0;
}

BOOL BrowseFile(HWND hwOwner,WORD btype,char *fnbuf)
{
      BOOL retval;
      WORD z;
      char szFile[128];
      char szFileTitle[128];
      char szFilter[140];
      OPENFILENAME ofn;

      switch (btype) {
            case 0:
                  lstrcpy(szFilter,"Program Files (*.exe)|*.exe||");
                  break;
            case 1:
                  lstrcpy(szFilter,"All Files (exe,dll,ico)|*.exe;*.dll;*.ico|Program Files (*.exe)|*.exe|DLL Files (*.dll)|*.dll|Icon Files (*.ico)|*.ico||");
                  break;
            case 2:
                  lstrcpy(szFilter,"Whack Files (*.wck)|*.wck||");
                  break;
            default:
                  return FALSE;
      }
// Change all delimiters in Filter to nulls
      for (z = 0; szFilter[z] != '\0'; z++) {
             if (szFilter[z] == '|')
                   szFilter[z] = '\0';
      }

      memset(&ofn, 0, sizeof(OPENFILENAME));  // Init & clear Structure

      szFile[0] = '\0';
      ofn.lStructSize = sizeof(OPENFILENAME);
      ofn.hwndOwner = hwOwner;
      ofn.lpstrFilter = szFilter;
      ofn.lpstrFile = szFile;
      ofn.nMaxFile = sizeof(szFile);
      ofn.lpstrFileTitle = szFileTitle;
      ofn.nMaxFileTitle = sizeof(szFileTitle);
      switch (btype) {
            case 0:
                  ofn.lpstrTitle = "Browse Executables";
                  ofn.lpstrDefExt = "EXE";
                  break;
            case 1:
                  ofn.lpstrTitle = "Browse Icons";
                  break;
            case 2:
                  ofn.lpstrTitle = "Browse Whacked Files";
                  ofn.lpstrDefExt = "WCK";
                  break;
      }
      ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
      retval = GetOpenFileName(&ofn);
      if (retval)
            lstrcpy(fnbuf,szFile);
      return retval;
}

void DrawBitmap(HDC hdc,HBITMAP hBitmap,WORD xstart,WORD ystart)
{
      BITMAP tempbm;
      HBITMAP hOldBmp;
      HDC hdcmem;
      POINT ptsize, ptorg;

      if (hBitmap == NULL)
            return;
      hdcmem = CreateCompatibleDC(hdc);
      hOldBmp = SelectObject(hdcmem,hBitmap);
      SetMapMode(hdcmem,GetMapMode(hdc));
      GetObject(hBitmap,sizeof(BITMAP),(LPSTR) &tempbm);
      ptsize.x = tempbm.bmWidth;
      ptsize.y = tempbm.bmHeight;
      DPtoLP(hdc,&ptsize,1);
      ptorg.x = 0;
      ptorg.y = 0;
      DPtoLP(hdcmem,&ptorg,1);
      BitBlt(hdc,xstart,ystart,ptsize.x,ptsize.y,hdcmem,ptorg.x,ptorg.y,SRCCOPY);
      SelectObject(hdcmem,hOldBmp);
      DeleteDC(hdcmem);
      return;
}


After you have translated it, please post the source here. Thanks!
0
 

Author Comment

by:DelFreak
ID: 6451794
Slavak, are you going to convert it?
0
 
LVL 3

Expert Comment

by:Slavak
ID: 6452367
I have not time just now. But I think the prefer way to update resources is use UpdateResource API function.
I did it sometime, but cannot find a code. For custom resources there is no problem, but grouped resources (such as icons) needs some trick. I'm not remember it just now :(.

Regards
0
 
LVL 1

Expert Comment

by:sundayboys
ID: 6455460
hi
  to download jedi-VCL component,it have a example for you want(have all sourcecode with delphi),this example name peViewer.
  jedi-vcl component:
URL ftp://delphi-jedi.org/Code_Library/Release_1_11/JCL.zip
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 6455511
Well, any resource editor should allow you to change it (if you are lucky enough to have MSVC then this is all you need).

Just open the resources of the application and change the ICON resource called MAINICON.

Cheers,

Raymond.
0
 

Author Comment

by:DelFreak
ID: 6467967
Does anyone else have any suggestions? I need code or maybe you can just convert the C code above. Thanks!
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 12

Expert Comment

by:rwilson032697
ID: 6468871
You don't need any source code! Just download a free resource editor (most should allow editing resources in EXEs) - http://www.google.com should find you a bunch in few seconds :-)

Cheers,

Raymond.
0
 

Author Comment

by:DelFreak
ID: 6469147
Yes but I would like to learn how to do such a thing in Delphi. If you have code that does this or if you can translate the code above then I would really appreciate it. Thanks!
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 6469183
There is a demo in Delphi called ResExplorer. It does not save changes but it would be a good place to start if you were interested in learning about this stuff...

Cheers,

Raymond.
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6469264
Hi Delfreak :-)

 Ok Ok here is a VERY simple-minded program that can change the icon of another delphi exe. It just changes it to a solid green block... but you can easily alter this code to allow you to replace the icon with another icon... this code seems to work fine... but I wrote it in about 15 mins so it's bound to have some silly bug somewhere so you better look it over carefully :-)

First go get ExeMod.pas at my web site http://delphi.does.it

Put ExeMod.pas into the same dir as your project and add ExeMod to your uses clause... then add 2 buttons to your form and double click them to add event handlers...now add an opendialog ... finally just replace the entire code of the project with this code... I hope it formats correctly
Oh... I added a routine in button 2 that changes the Icon of your exe while it is running..... just click it and the icon will change to a green block.... button1 changes the icon of another exe :-)


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExeMod;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button2Click(Sender: TObject);
Var
SearchStr: String;
x: Integer;
begin
ReadExe;
SearchStr := chr(192)+chr(192)+chr(0)+chr(128)+chr(128)+chr(128)+chr(0)+chr(0)+chr(0)+chr(255)+chr(0)
+chr(0)+chr(255)+chr(0)+chr(0)+chr(0)+chr(255)+chr(255)+chr(0)+chr(255)+chr(0)
+chr(0)+chr(0)+chr(255)+chr(0)+chr(255)+chr(0)+chr(255)+chr(255)+chr(0)+chr(0);
SearchStr := SearchStr +chr(255)+chr(255)+chr(255)+chr(0);
if  pos(SearchStr,Exe) = 0 then exit;
for x := (pos(SearchStr,Exe)+35) to (pos(SearchStr,Exe))+546 do
  begin
    Exe[x] := chr(170);
  end;
  AlterExe;
end;

procedure TForm1.Button1Click(Sender: TObject);
Var
MyString,SearchStr: String;
x: Integer;
begin
  OpenDialog1.Execute;
  MyString := File2String(OpenDialog1.FileName);
  SearchStr := chr(192)+chr(192)+chr(0)+chr(128)+chr(128)+chr(128)+chr(0)+chr(0)+chr(0)+chr(255)+chr(0)
  +chr(0)+chr(255)+chr(0)+chr(0)+chr(0)+chr(255)+chr(255)+chr(0)+chr(255)+chr(0)
  +chr(0)+chr(0)+chr(255)+chr(0)+chr(255)+chr(0)+chr(255)+chr(255)+chr(0)+chr(0);
  SearchStr := SearchStr +chr(255)+chr(255)+chr(255)+chr(0);
  if pos(SearchStr,MyString) > 0 then
  begin
    for x := (pos(SearchStr,MyString)+35) to (pos(SearchStr,MyString))+546 do
    begin
      MyString[x] := chr(170);
    end;
  String2File(MyString,OpenDialog1.FileName);
  showmessage('ICON found and changed');
  end
  else showmessage('ICON not found in file');
end;

end.
 

0
 
LVL 5

Expert Comment

by:Gwena
ID: 6469336
Oh... there is 128 more bytes that follow the block I changed above... they are also part of the icon data... I just changed enough data to make a nice green blob :-)  but to change the icon with another one you would need to add those as well.... I wrote a funny program just now that alters the exe's icon randomly every time it runs... it should make people curious... it would be easy to grab an icon from another exe at random and swap for that each time too... or make the icon count the number of times the exe has been run.. and display it in a colorful hex number... 00 to FF :-)
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 6469358
Gwena,

You are thinking evil thoughts - I can tell. This would be the basis of a pretty funny trojan - well, until the Feds caught up with you of course!

Cheers,

Raymond.
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6469451
Hi rwilson :-)

   There's not an ounce of mischief in me! I just like to write strange and mostly useless code...that's all :-)
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6469595
This code lets you select a new .ico file by clicking button1 .. then you click button 2 to choose a delphi exe to insert the .ico into..  This is far from perfect but it works (at least it seems to) and it's something for you to fill out with some more code and experiment with... I wish I had more time so I could write some better code to do this... I tried this a couple of times on delphi exe's ... no idea what will happen with other exe files.... better back up any file before you attempt to operate on it with this code :-)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExeMod;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  IconStr: String;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.Execute;
  If Pos('.ico',OpenDialog1.FileName) > 0 then IconStr := File2String(OpenDialog1.FileName);
  delete(IconStr,1,126);
end;


procedure TForm1.Button2Click(Sender: TObject);
Var
MyString,SearchStr: String;
x: Integer;
begin
  OpenDialog1.Execute;
  MyString := File2String(OpenDialog1.FileName);
  SearchStr := chr(192)+chr(192)+chr(0)+chr(128)+chr(128)+chr(128)+chr(0)+chr(0)+chr(0)+chr(255)+chr(0)
  +chr(0)+chr(255)+chr(0)+chr(0)+chr(0)+chr(255)+chr(255)+chr(0)+chr(255)+chr(0)
  +chr(0)+chr(0)+chr(255)+chr(0)+chr(255)+chr(0)+chr(255)+chr(255)+chr(0)+chr(0);
  SearchStr := SearchStr +chr(255)+chr(255)+chr(255)+chr(0);
  if pos(SearchStr,MyString) > 0 then
  begin
    for x := 1 to 640 do
    begin
      MyString[(pos(SearchStr,MyString)+34)+x] := IconStr[x];
    end;
  String2File(MyString,OpenDialog1.FileName);
  showmessage('ICON found and changed');
  end
  else showmessage('ICON not found in file');
end;

end.


0
 
LVL 2

Accepted Solution

by:
bugroger earned 123 total points
ID: 6470428
hi,

here is a function that lets you change the icon of all exe-files in a directory.



Before you can use this function you must make the "iconhckr.pas" and "headers.pas".
!!! you must use these units and not the one which "iconhack.zip" includes.
    I have make same changes !!!

Good luck!
 Bug

Uses IconHckr;

VAR
 ThreadString : string;

//ex: If not UpdateAllExeIcons('C:\Apps', TRUE, 'C:\NewIcon.ico') then ShowMessage('Error')
//                                                                else ShoeMessage('OK')
//note: the icon can only be changed if the icon in the exe and the IconFile(.ico)
//      have the same size
//      otherwise you get an error !!!
Function UpdateAllExeIcons(Dir : String; RecurseSubDirs : Boolean; IconFile : String) : Boolean;
VAR
 ExeNames : TStrings;
 z        : Integer;

 Function SetIconToExe(IconFileName, ExeFileName : String) : Boolean;
 VAR
  RFile : TResourceFile;

   function IconEnumCallBack(szIconName: PANSICHAR ): BOOLEAN;
   begin
    ThreadString      := szIconName;
    Result            := FALSE;
   end;

 Begin
  IF (FileExists(ExeFileName)) AND (FileExists(IconFileName)) then
  Begin
   RFile := TResourceFile.Create(PChar(ExeFileName));
   IF RFile.EnumIcons(@IconEnumCallBack) then
   Begin
    IF not RFile.UpdateIcon(PCHAR(ThreadString), PCHAR(IconFileName)) then Result := FALSE;
   End else Result := FALSE;
   RFile.Free;
  End else Result := FALSE;
 End;

 Procedure GetFiles(Dir, FileMask : String; RecurseSubDirs : Boolean; Names : TStrings);
 Function InFileMaskString(s : string) : Boolean;
 Var
  i : Integer;
 Begin
  Result := FALSE;
  Repeat
   i := Pos(s, FileMask);
   IF i <> 0 then
    IF (FileMask[i] = '.')and(FileMask[i + Length(s)] = ';') then
    Begin
     i := 0;
     Result := TRUE;
    End;
  Until i = 0;
 End;

 Function GetDir : string;
 VAR
  p : integer;
 begin
  p := pos(';', Dir);
  IF p = 0 then
  Begin
   Result := DIR;
   DIR := '';
  End else
  Begin
   Result := Copy(Dir, 1, p -1);
   Delete(Dir , 1, p);
  End;
 end;

 Procedure _GetFiles(StartDir : string);
 var
  SR : tSearchRec;
  ERG : integer;

 begin
  IF StartDir[Length(StartDir)]<>'\' then StartDir := StartDir + '\';

  ERG := findfirst(StartDir+'*.*', faANYFILE, SR);
  While (ERG = 0) do
  begin
   //IF it a directory and RECURSESUBDIRS then step in
   IF (SR.Attr and faDirectory > 0)and(SR.Name[1] <> '.')and RecurseSubDirs
     then _GetFiles(StartDir + SR.Name)
     else
   //else
   IF (SR.Name[1] <> '.')and(InFileMaskString(ExtractFileExt(SR.Name)))then
   Begin
    Names.Add(StartDir + SR.Name);
   End;
   ERG := FindNext(SR);
   Application.ProcessMessages;
  end;
  FindClose(SR);
 end;
 Begin
  IF FileMask[Length(FileMask)] <> ';' then FileMask := FileMask + ';';

  Repeat
   _GetFiles(GetDir);
  Until Dir = '';
 End;


Begin
 ExeNames := TStringList.Create;
 GetFiles(Dir, '*.exe', RecurseSubDirs, ExeNames);
 For z := 0 to ExeNames.Count -1 do
 Begin
  IF not SetIconToExe(IconFile, ExeNames.Strings[z]) then
  Begin
   Result := FALSE;
   Break;
  End;
 End;
 ExeNames.Free;
End;



------------------------------ start of "headers.pas" -------------------------------
unit Headers;

interface

const
  IMAGE_DOS_SIGNATURE    = $5A4D;      (* MZ *)
  IMAGE_OS2_SIGNATURE    = $454E;      (* NE *)
  IMAGE_OS2_SIGNATURE_LE = $454C;      (* LE *)
  IMAGE_VXD_SIGNATURE    = $454C;      (* LE *)
  IMAGE_NT_SIGNATURE     = $00004550;  (* PE00 *)

type
  TMZHeader = packed record
    e_Magic    : Word;                      (* Magic Number - MZ *)
    e_cblp     : Word;                      (* Bytes on late page of file *)
    e_cp       : Word;                      (* Pages in file *)
    e_crlc     : Word;                      (* Relocations *)
    e_cparhdr  : Word;                      (* Size of header in paragraphs *)
    e_minalloc : Word;                      (* Minimum extra paragraphs needed *)
    e_maxalloc : Word;                      (* Maximum extra paragraphs needed *)
    e_ss       : Word;                      (* Initial (relative) SS value *)
    e_sp       : Word;                      (* Initial SP value *)
    e_csum     : Word;                      (* Checksum *)
    e_ip       : Word;                      (* Initial IP value *)
    e_cs       : Word;                      (* Initial (relative) CS value *)
    e_lfarlc   : Word;                      (* File Address of relocation tables *)
    e_ovno     : Word;                      (* Overlay number *)
    e_res      : Array [ 0 .. 3 ] of Word;  (* Reserved Words *)
    e_oemid    : Word;                      (* OEM identifier (for e_oeminfo) *)
    e_oeminfo  : Word;                      (* OEM information; e_oemid specific *)
    e_res2     : Array [ 0 .. 9 ] of Word;  (* Reserved words *)
    e_lfanew   : LongInt;                   (* File address of new exe header *)
  end;

type
  TNEHeader = packed record
    ne_magic        : Word;                     (* Magic number NE *)
    ne_ver          : Byte;                     (* Version Number *)
    ne_rev          : Byte;                     (* Revision Number *)
    ne_enttab       : Word;                     (* Offset of Entry Table *)
    ne_cbenttab     : Word;                     (* Number of bytes in Entry Table *)
    ne_crc          : LongInt;                  (* Checksum of whole of file *)
    ne_flags        : Word;                     (* Flag word *)
    ne_autodata     : Word;                     (* Automatic data segment number *)
    ne_heap         : Word;                     (* Initial heap allocation *)
    ne_stack        : Word;                     (* Initial stack allocation *)
    ne_csip         : LongInt;                  (* Initial CS:IP setting *)
    ne_sssp         : LongInt;                  (* Initial SS:SP setting *)
    ne_cseg         : Word;                     (* Count of file segements *)
    ne_cmod         : Word;                     (* Entries in Module Reference Table *)
    ne_cbnrestab    : Word;                     (* Size of non-resident name table *)
    ne_segtab       : Word;                     (* Offset of segment table *)
    ne_rsrctab      : Word;                     (* Offset of resource table *)
    ne_restab       : Word;                     (* Offset of resident name table *)
    ne_modtab       : Word;                     (* Offset of module reference table *)
    ne_imptab       : Word;                     (* Offset of imported names table *)
    ne_nrestab      : LongInt;                  (* Offset of non-resident names table - relative to entire file *)
    ne_cmovent      : Word;                     (* Count of moveable entries *)
    ne_align        : Word;                     (* Segment alignment shift count *)
    ne_cres         : Word;                     (* Count of resource segments *)
    ne_exetyp       : Byte;                     (* Target Operating System *)
    ne_flagsothers  : Byte;                     (* Other .EXE flags *)
    ne_pretthunks   : Word;                     (* Offset to return thunks *)
    ne_psegrefbytes : Word;                     (* Offset to segment reference bytes *)
    ne_swaparea     : Word;                     (* Minimum code swap area size *)
    ne_expver       : Word;                     (* Expected Windows version number *)
  end;

type
  PIMAGE_FILE_HEADER = ^TIMAGE_FILE_HEADER;
  TIMAGE_FILE_HEADER = packed record
    Machine              : WORD;
    NumberOfSections     : WORD;
    TimeDateStamp        : LONGINT;
    PointerToSymbolTable : LONGINT;
    NumberOfSymbols      : LONGINT;
    SizeOfOptionalHeader : WORD;
    Characteristics      : WORD;
  end;

type
  PIMAGE_DATA_DIRECTORY = ^TIMAGE_DATA_DIRECTORY;
  TIMAGE_DATA_DIRECTORY = packed record
    VirtualAddress : LONGINT;
    Size           : LONGINT;
  end;

const
  IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;

type
  PIMAGE_OPTIONAL_HEADER = ^TIMAGE_OPTIONAL_HEADER;
  TIMAGE_OPTIONAL_HEADER = packed record
    Magic                       : WORD;
    MajorLinkerVersion          : BYTE;
    MinorLinkerVersion          : BYTE;
    SizeOfCode                  : LONGINT;
    SizeOfInitializedData       : LONGINT;
    SizeOfUninitializedData     : LONGINT;
    AddressOfEntryPoint         : LONGINT;
    BaseOfCode                  : LONGINT;
    BaseOfData                  : LONGINT;
    ImageBase                   : LONGINT;
    SectionAlignment            : LONGINT;
    FileAlignment               : LONGINT;
    MajorOperatingSystemVersion : WORD;
    MinorOperatingSystemVersion : WORD;
    MajorImageVersion           : WORD;
    MinorImageVersion           : WORD;
    MajorSubsystemVersion       : WORD;
    MinorSubsystemVersion       : WORD;
    Win32VersionValue           : LONGINT;
    SizeOfImage                 : LONGINT;
    SizeOfHeaders               : LONGINT;
    CheckSum                    : LONGINT;
    Subsystem                   : WORD;
    DllCharacteristics          : WORD;
    SizeOfStackReserve          : LONGINT;
    SizeOfStackCommit           : LONGINT;
    SizeOfHeapReserve           : LONGINT;
    SizeOfHeapCommit            : LONGINT;
    LoaderFlags                 : LONGINT;
    NumberOfRvaAndSizes         : LONGINT;
    DataDirectory               : Array [ 0 .. (IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1)] of TIMAGE_DATA_DIRECTORY;
  end;

type
  PIMAGE_NT_HEADERS = ^TIMAGE_NT_HEADERS;
  TIMAGE_NT_HEADERS = packed record
    Signature      : LONGINT;
    FileHeader     : TIMAGE_FILE_HEADER;
    OptionalHeader : TIMAGE_OPTIONAL_HEADER;
  end;

const
  IMAGE_DIRECTORY_ENTRY_EXPORT         = 0;  
  IMAGE_DIRECTORY_ENTRY_IMPORT         = 1;  
  IMAGE_DIRECTORY_ENTRY_RESOURCE       = 2;  
  IMAGE_DIRECTORY_ENTRY_EXCEPTION      = 3;  
  IMAGE_DIRECTORY_ENTRY_SECURITY       = 4;  
  IMAGE_DIRECTORY_ENTRY_BASERELOC      = 5;  
  IMAGE_DIRECTORY_ENTRY_DEBUG          = 6;  
  IMAGE_DIRECTORY_ENTRY_COPYRIGHT      = 7;
  IMAGE_DIRECTORY_ENTRY_GLOBALPTR      = 8;  
  IMAGE_DIRECTORY_ENTRY_TLS            = 9;  
  IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    = 10;  
  IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   = 11;  
  IMAGE_DIRECTORY_ENTRY_IAT            = 12;  

const
  IMAGE_SIZEOF_SHORT_NAME = 8;

type
  PIMAGE_SECTION_HEADER = ^TIMAGE_SECTION_HEADER;
  TIMAGE_SECTION_HEADER = packed record
    Name                 : Array [ 0 .. (IMAGE_SIZEOF_SHORT_NAME - 1) ] of CHAR;
    VirtualSize          : LONGINT;
    VirtualAddress       : LONGINT;
    SizeOfRawData        : LONGINT;
    PointerToRawData     : LONGINT;
    PointerToRelocations : LONGINT;
    PointerToLinenumbers : LONGINT;
    NumberOfRelocations  : WORD;
    NumberOfLinenumbers  : WORD;
    Characteristics      : LONGINT;
  end;

const
  IMAGE_SIZEOF_SECTION_HEADER = 40;

type
  PIMAGE_RESOURCE_DIRECTORY = ^TIMAGE_RESOURCE_DIRECTORY;
  TIMAGE_RESOURCE_DIRECTORY = packed record
    Characteristics      : LONGINT;
    TimeDateStamp        : LONGINT;
    MajorVersion         : WORD;
    MinorVersion         : WORD;
    NumberOfNamedEntries : WORD;
    NumberOfIDEntries    : WORD;
  end;

const
  IMAGE_RESOURCE_NAME_IS_STRING    = $80000000;
  IMAGE_RESOURCE_DATA_IS_DIRECTORY = $80000000;


type
  PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^TIMAGE_RESOURCE_DIRECTORY_ENTRY;
  TIMAGE_RESOURCE_DIRECTORY_ENTRY = packed record
    Name   : LONGINT;
    Offset : LONGINT;
  end;

type
  PIMAGE_RESOURCE_DATA_ENTRY = ^TIMAGE_RESOURCE_DATA_ENTRY;
  TIMAGE_RESOURCE_DATA_ENTRY = packed record
    OffsetToData : LONGINT;
    Size         : LONGINT;
    CodePage     : LONGINT;
    Reserved     : LONGINT;
  end;

type
  PICON_HEADER = ^TICON_HEADER;
  TICON_HEADER = packed record
    wReserved : WORD;
    wType     : WORD;
    wCount    : WORD;
  end;

type
  PFILE_ICON_HEADER = ^TFILE_ICON_HEADER;
  TFILE_ICON_HEADER = packed record
    wReserved : WORD;
    wType     : WORD;
    wCount    : WORD;
  end;

type
  TICON_RESOURCE = packed record
    bWidth       : BYTE;
    bHeight      : BYTE;
    bColorCount  : BYTE;
    bReserved    : BYTE;
    wPlanes      : WORD;
    wBitCount    : WORD;
    lBytesInRes  : LONGINT;
    wNameOrdinal : WORD;
  end;

type
  TFILE_ICON_RESOURCE = packed record
    bWidth       : BYTE;
    bHeight      : BYTE;
    bColorCount  : BYTE;
    bReserved    : BYTE;
    wPlanes      : WORD;
    wBitCount    : WORD;
    lBytesInRes  : LONGINT;
    lImageOffset : LONGINT;
  end;

implementation
{


   DW   Alignment shift count for resource data.

   A table of resource type information blocks follows. The following
   is the format of each type information block:

        DW  Type ID. This is an integer type if the high-order bit is
            set (8000h); otherwise, it is an offset to the type string,
            the offset is relative to the beginning of the resource
            table. A zero type ID marks the end of the resource type
            information blocks.

        DW  Number of resources for this type.

        DD  Reserved.

        A table of resources for this type follows. The following is
        the format of each resource (8 bytes each):

            DW  File offset to the contents of the resource data,
                relative to beginning of file. The offset is in terms
                of the alignment shift count value specified at
                beginning of the resource table.

            DW  Length of the resource in the file (in bytes).

            DW  Flag word.
                0010h = MOVEABLE  Resource is not fixed.
                0020h = PURE      Resource can be shared.
                0040h = PRELOAD   Resource is preloaded.

            DW  Resource ID. This is an integer type if the high-order
                bit is set (8000h), otherwise it is the offset to the
                resource string, the offset is relative to the
                beginning of the resource table.

            DD  Reserved.

   Resource type and name strings are stored at the end of the
   resource table. Note that these strings are NOT null terminated and
   are case sensitive.

   DB   Length of the type or name string that follows. A zero value
        indicates the end of the resource type and name string, also
        the end of the resource table.

   DB   ASCII text of the type or name string.
}
end.

----------------------------------------- end of "headers.pas" ------------------------------


--------------------------------- start of "iconhckr.pas" -----------------------------------
unit Iconhckr;

interface

uses WinTypes,
     WinProcs,
     SysUtils,
     Headers;

type
  PANSICHAR = PCHAR;

const
  MAX_PATH = 144;

const
  RT_GROUPICON = MAKEINTRESOURCE(14);

type
  EResourceError = class(Exception);

(*
 * TICONENUMERATOR is a callback function that
 * recieves the names of the RT_GROUP_ICON resources
 * in a given image.
 *
 * Return :
 *   TRUE - continue enumeration
 *  FALSE - stop now.
 *)
type
//  TICONENUMERATOR = function ( szIconName: PANSICHAR ): BOOLEAN of Object;
  TICONENUMERATOR = function ( szIconName: PANSICHAR ): BOOLEAN;

type
  TResourceFile = class
    constructor Create ( szFileName: PANSICHAR );

    (*
     * FindIcon
     *
     * Locates the given Icon ID in the resource file.
     *
     * szResourceID - the name of the resouce or the ID in MAKEINTRESOURCE format.
     *
     * Returns:
     *   0 : The requested icon was not found in the file.
     *  !0 : The handle to the icon (actually file position)
     *)
    function FindIcon ( szResourceID: PANSICHAR ): LONGINT;

    (*
     * UpdateIcon
     *
     * Locates the specified resource and moves the given icons into
     * the exe file.
     *
     * szResourceID - the name of the resource or the ID in MAKEINTRESOURCE format.
     * szIcon - the name of the .ICO file.
     *
     * Returns:
     *   TRUE - successful
     *  FALSE - failed
     *)
    function UpdateIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;

    (*
     * EnumIcons
     *
     * Enumerates through all icons in the current image file.
     * Calls the method given by lpfnCallback for each icon.
     *
     * lpfnCallback - the method address to call for each icon.
     *
     * Returns:
     *   TRUE - the function was successful, does not guarentee that
     *          the callback function was called.
     *
     *  FALSE - the function failed.
     *
     *)
    function EnumIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;

    (*
     * UpdateIconFromImage
     *
     * Updates an icon from another TResourceFile.
     *
     * szResourceID - the name of the resource to be updated (destination)
     * ResFile      - the TResourceFile class from which the icon is to be retrieved
     * szSourceID   - the name of the source icon.
     *
     * Returns:
     *   TRUE - succesful
     *  FALSE - failed
     *)
    function UpdateIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile; szSourceID: PANSICHAR ): BOOLEAN;

    (*
     * GetIconDIB
     *
     * Returns the physical offset in the TResourceFile where
     * the DIB for the specified icon can be found.
     *
     * szResourceID - the name of the icon to find (comes from the RT_GROUP_ICON resource)
     *
     * Returns:
     *   0 : failed
     *   > 0 : the offset of the dib in the image.
     *)
    function GetIconDIB ( szResourceID: PANSICHAR ): LONGINT;

    destructor Destroy; override;
  private
    function FindNEIcon ( szResourceID: PANSICHAR ): LONGINT;
    function FindPEIcon ( szResourceID: PANSICHAR ): LONGINT;

    function GetPEIconDIB ( szResourceID: PANSICHAR ): LONGINT;
    function GetNEIconDIB ( szResourceID: PANSICHAR ): LONGINT;

    (* PE helper routines *)
    function ImageDirectoryOffset ( dwIMAGE_DIRECTORY : LONGINT; var VirtualAddress: LONGINT ): LONGINT;
    function SectionHeaderOffset: LONGINT;

    function UpdatePEIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;
    function UpdateNEIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;

    function EnumPEIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;
    function EnumNEIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;

    function UpdatePEIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile; szSourceID: PANSICHAR ): BOOLEAN;
    function UpdateNEIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile; szSourceID: PANSICHAR ): BOOLEAN;

  private
    m_szFileName : PANSICHAR;         (* Name of the file *)
    m_file       : FILE;              (* File variable *)
    m_bPortable  : BOOLEAN;           (* True, image is a PE; FALSE, image is an NE *)
    m_MZHeader   : TMZHeader;         (* DOS exe header - common to all images *)
    m_NEHeader   : TNEHeader;         (* Win16 header *)
    m_PEHeader   : TIMAGE_NT_HEADERS; (* Win32 header *)
  end;

implementation

constructor TResourceFile.Create ( szFileName: PANSICHAR );
var nReadCount : CARDINAL;
begin
  (* must have a valid szFileName .. *)
  if (not(Assigned(szFileName))) or
     (IsBadStringPtr(szFileName, MAX_PATH)) then
    raise EResourceError.Create('File name is NIL');

  (* might raise a memory exception here *)
  m_szFileName := StrNew(szFileName);

  (* make sure IOResult doesn't cause a problem to keep us from opening the file *)
  if (IOResult = 0) then;
  AssignFile(m_file, m_szFileName);
  Reset(m_file, 1);
  if (IOResult <> 0) then
    raise EResourceError.Create('Unable to open file');

  BlockRead(m_file, m_MZHeader, SizeOf(m_MZHeader), nReadCount);
  if (nReadCount <> SizeOf(m_MZHeader)) or
     (m_MZHeader.e_magic <> IMAGE_DOS_SIGNATURE) or
     (m_MZHeader.e_lfanew = 0) then
    raise EResourceError.Create('Invalid image');

  (*
   * The two blocks below assume that all PEs and NEs are large
   * enough to contain both the PE header and an NE header..
   *
   * Hopefully, this assumption will never be proven incorrect.
   *)

  Seek(m_file, m_MZHeader.e_lfanew);
  BlockRead(m_file, m_NEHeader, SizeOf(m_NEHeader), nReadCount);
  if (nReadCount <> SizeOf(m_NEHeader)) then
    raise EResourceError.Create('Invalid image');

  Seek(m_file, m_MZHeader.e_lfanew);
  BlockRead(m_file, m_PEHeader, SizeOf(m_PEHeader), nReadCount);
  if (nReadCount <> SizeOf(m_PEHeader)) then
    raise EResourceError.Create('Invalid image');

  if (m_NEHeader.ne_magic = IMAGE_OS2_SIGNATURE) then
  begin
    m_bPortable := FALSE;
  end else
  if (m_PEHeader.Signature = IMAGE_NT_SIGNATURE) then
  begin
    m_bPortable := TRUE;
  end else
    raise EResourceError.Create('Invalid image, must be a PE or NE.');
end;

function TResourceFile.FindIcon ( szResourceID: PANSICHAR ): LONGINT;
begin
  Result := 0;
  if (Assigned(szResourceID)) then
  begin
    (* Punt to the appropriate routine for the given file *)
    if (m_bPortable) then
      Result := FindPEIcon(szResourceID)
    else
      Result := FindNEIcon(szResourceID);
  end;
end;

function TResourceFile.GetNEIconDIB ( szResourceID: PANSICHAR ): LONGINT;
var ResTable    : LONGINT;
    ResAlign    : WORD;

    ResType     : WORD;
    ResCount    : WORD;
    ResReserved : LONGINT;

    nCount      : INTEGER;

    ResOffset   : WORD;
    ResLength   : WORD;
    ResFlags    : WORD;
    ResID       : WORD;
    ResResd     : LONGINT;

  function CompareName ( Name: WORD ): BOOLEAN;
  var SavedPos  : LONGINT;
      nLen      : BYTE;
      NameChars : Array [ 0 .. 255 ] of CHAR;
  begin
    Result := FALSE;
    if (HIWORD(LONGINT(szResourceID)) = 0) then
    begin
      if (Name and $8000 = $8000) then
      begin
        Result := (Name and not($8000) = LONGINT(szResourceID));
      end;
    end else
    begin
      if (Name and $8000 = 0) then
      begin
        SavedPos := FilePos(m_File);

        Seek(m_File, ResTable + Name);
        BlockRead(m_File, nLen, SizeOf(nLen));
        BlockRead(m_File, NameChars, nLen);

        NameChars[nLen] := #0;
        Result := (StrComp(szResourceID, NameChars) = 0);

        Seek(m_file, SavedPos);
      end;
    end;
  end;

begin
  ResTable := LONGINT(m_MZHeader.e_lfanew) + m_NEHeader.ne_rsrctab;

  Seek(m_File, ResTable);
  BlockRead(m_File, ResAlign, SizeOf(ResAlign));

  BlockRead(m_File, ResType, SizeOf(ResType));
  BlockRead(m_File, ResCount, SizeOf(ResCount));
  BlockRead(m_File, ResReserved, SizeOf(ResReserved));

  while (ResType <> 0) do
  begin

    if (ResType and $8000 = $8000) and
       ((ResType and not ($8000)) = LONGINT(RT_ICON)) then
    begin
      for nCount := 0 to (INTEGER(ResCount) - 1) do
      begin
        BlockRead(m_File, ResOffset, SizeOf(ResOffset));
        BlockRead(m_File, ResLength, SizeOf(ResLength));
        BlockRead(m_File, ResFlags, SizeOf(ResFlags));
        BlockRead(m_File, ResID, SizeOf(ResID));
        BlockRead(m_File, ResResd, SizeOf(ResResd));

        if (CompareName(ResID)) then
        begin
          Result := ResOffset * (1 shl ResAlign);
          break;
        end;
      end;
      break;
    end else
      Seek(m_File, FilePos(m_File) + ResCount * 12);

    BlockRead(m_File, ResType, SizeOf(ResType));
    BlockRead(m_File, ResCount, SizeOf(ResCount));
    BlockRead(m_File, ResReserved, SizeOf(ResReserved));
  end;
end;

function TResourceFile.FindNEIcon ( szResourceID: PANSICHAR ): LONGINT;
var ResTable    : LONGINT;
    ResAlign    : WORD;

    ResType     : WORD;
    ResCount    : WORD;
    ResReserved : LONGINT;

    nCount      : INTEGER;

    ResOffset   : WORD;
    ResLength   : WORD;
    ResFlags    : WORD;
    ResID       : WORD;
    ResResd     : LONGINT;

  function CompareName ( Name: WORD ): BOOLEAN;
  var SavedPos  : LONGINT;
      nLen      : BYTE;
      NameChars : Array [ 0 .. 255 ] of CHAR;
  begin
    Result := FALSE;
    if (HIWORD(LONGINT(szResourceID)) = 0) then
    begin
      if (Name and $8000 = $8000) then
      begin
        Result := (Name and not($8000) = LONGINT(szResourceID));
      end;
    end else
    begin
      if (Name and $8000 = 0) then
      begin
        SavedPos := FilePos(m_File);

        Seek(m_File, ResTable + Name);
        BlockRead(m_File, nLen, SizeOf(nLen));
        BlockRead(m_File, NameChars, nLen);

        NameChars[nLen] := #0;
        Result := (StrComp(szResourceID, NameChars) = 0);

        Seek(m_file, SavedPos);
      end;
    end;
  end;

begin
  ResTable := LONGINT(m_MZHeader.e_lfanew) + m_NEHeader.ne_rsrctab;

  Seek(m_File, ResTable);
  BlockRead(m_File, ResAlign, SizeOf(ResAlign));

  BlockRead(m_File, ResType, SizeOf(ResType));
  BlockRead(m_File, ResCount, SizeOf(ResCount));
  BlockRead(m_File, ResReserved, SizeOf(ResReserved));

  while (ResType <> 0) do
  begin

    if (ResType and $8000 = $8000) and
       ((ResType and not ($8000)) = LONGINT(RT_GROUP_ICON)) then
    begin
      for nCount := 0 to (INTEGER(ResCount) - 1) do
      begin
        BlockRead(m_File, ResOffset, SizeOf(ResOffset));
        BlockRead(m_File, ResLength, SizeOf(ResLength));
        BlockRead(m_File, ResFlags, SizeOf(ResFlags));
        BlockRead(m_File, ResID, SizeOf(ResID));
        BlockRead(m_File, ResResd, SizeOf(ResResd));

        if (CompareName(ResID)) then
        begin
          Result := ResOffset * (1 shl ResAlign);
          break;
        end;
      end;
      break;
    end else
      Seek(m_File, FilePos(m_File) + ResCount * 12);

    BlockRead(m_File, ResType, SizeOf(ResType));
    BlockRead(m_File, ResCount, SizeOf(ResCount));
    BlockRead(m_File, ResReserved, SizeOf(ResReserved));
  end;

end;

function TResourceFile.SectionHeaderOffset: LONGINT;
begin
  Result := m_MZHeader.e_lfanew + SizeOf(TIMAGE_FILE_HEADER) + SizeOf(TIMAGE_OPTIONAL_HEADER) + SizeOf(LONGINT);
end;

function TResourceFile.ImageDirectoryOffset ( dwIMAGE_DIRECTORY : LONGINT; var VirtualAddress: LONGINT ): LONGINT;
var nSections  : WORD;
    VAImageDir : LONGINT;
    shOffset   : LONGINT;
    sh         : TIMAGE_SECTION_HEADER;
    nReadCount : INTEGER;
    i          : INTEGER;
begin
  nSections := m_PEHeader.FileHeader.NumberOfSections;
  VirtualAddress := 0;

  (* must be 0 thru (NumberOfRVAandSizes - 1) *)
  if (dwIMAGE_DIRECTORY >= (m_PEHeader.OptionalHeader.NumberOfRvaAndSizes - 1)) then
  begin
    Result := 0;
    exit;
  end;

  (* Locate image directory's RVA *)
  VAImageDir := m_PEHeader.OptionalHeader.dataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;

  (* Find the section containing the image directory *)
  i := 0;
  shOffset := SectionHeaderOffset;
  Seek(m_file, shOffset);
  while (i < nSections) do
  begin
    BlockRead(m_file, sh, SizeOf(sh), nReadCount);
    if (nReadCount = SizeOf(sh)) then
    begin
      if (sh.VirtualAddress <= VAImageDir) and
         (sh.VirtualAddress + sh.SizeOfRawData > VAImageDir) then
      begin
        VirtualAddress := sh.VirtualAddress;
        break;
      end;
    end;
    Inc(i);
  end;

  if (i >= nSections) then
  begin
    Result := 0;
    exit;
  end;

  (* Return the image directory offset *)
  Result := sh.PointerToRawData;
end;

function TResourceFile.GetPEIconDIB ( szResourceID: PANSICHAR ): LONGINT;
var ResourceOffset : LONGINT;
    VirtualAddress : LONGINT;
    Directory      : TIMAGE_RESOURCE_DIRECTORY;
    Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
    nRead          : CARDINAL;
    nCount, nCount_1 : INTEGER;
    DataOfs        : LONGINT;

  procedure SeekData ( Offset: LONGINT );
  begin
    (* have to mask out the msb *)
    Seek(m_file, ResourceOffset + (Offset and not($80000000)));
  end;

  function CompareName ( Name: LONGINT ): BOOLEAN;
  var SavedPos   : LONGINT;
      NameLength : WORD;
      NameChar   : WORD;
      nRead      : INTEGER;
      szName     : PCHAR;
  begin
    (*
     * This function does a cheap comparison of ANSI and UNICODE
     * characters.. it should be exact as long as the image is
     * English..
     *)
    Result := FALSE;
    if (HIWORD(LONGINT(szResourceID)) = 0) then
    begin
      if (Name and $80000000 = 0) then
      begin
        if (Name and not($80000000) = LONGINT(szResourceID)) then
        begin
          Result := TRUE;
          exit;
        end;
      end;
    end else
    begin
      if (Name and $80000000 <> 0) then
      begin
        SavedPos := FilePos(m_file);

        SeekData(Name);

        BlockRead(m_file, NameLength, SizeOf(NameLength), nRead);
        if (nRead <> SizeOf(NameLength)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;

        (* validate that the name is the proper length *)
        if (NameLength <> StrLen(szResourceID)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;

        szName := szResourceID;
        BlockRead(m_file, NameChar, Sizeof(NameChar), nRead);
        if (nRead <> SizeOf(NameChar)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;
        while (BYTE(szName^) = NameChar) and
              (szName^ <> #0) do
        begin
          Inc(szName);

          BlockRead(m_file, NameChar, Sizeof(NameChar), nRead);
          if (nRead <> SizeOf(NameChar)) then
          begin
            Seek(m_File, SavedPos);
            exit;
          end;
        end;

        Result := (szName^ = #0);
        Seek(m_File, SavedPos);
      end;
    end;
  end;

  function GetIconData ( Offset: LONGINT ): LONGINT;
  var Directory      : TIMAGE_RESOURCE_DIRECTORY;
      Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
      Resource       : TIMAGE_RESOURCE_DATA_ENTRY;
      nRead          : CARDINAL;
  begin
    Result := 0;

    SeekData(Offset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* this always assumes the first entry is the correct icon *)
    (* this may not be the case if the icon has multiple versions or languages.. *)

    BlockRead(m_File, Entry, SizeOf(Entry), nRead);
    if (nRead <> SizeOf(Entry)) then
      exit;

    SeekData(Entry.Offset);

    BlockRead(m_File, Resource, SizeOf(Resource), nRead);
    if (nRead <> SizeOf(Resource)) then
      exit;

    Result := (Resource.OffsetToData - VirtualAddress) + ResourceOffset;
  end;

begin
  Result := 0;
  (* Find the offset to the .rsrc section *)
  ResourceOffset := ImageDirectoryOffset(IMAGE_DIRECTORY_ENTRY_RESOURCE, VirtualAddress);

  if (ResourceOffset <> 0) then
  begin
    Seek(m_File, ResourceOffset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* find the icon directory .. *)
    for nCount := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
    begin
      BlockRead(m_File, Entry, SizeOf(Entry), nRead);
      if (nRead <> SizeOf(Entry)) then
        exit;

      (* this doesn't bother checking if it's a directory pointer.. just assumes it is *)
      if (Entry.Name = LONGINT(RT_ICON)) then
      begin
        SeekData(Entry.Offset);
        BlockRead(m_File, Directory, SizeOf(Directory), nRead);
        if (nRead <> SizeOf(Directory)) then
          exit;

        (* this could be a bit smarter to just to check the named or id'd entries *)
        for nCount_1 := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
        begin
          BlockRead(m_File, Entry, SizeOf(Entry), nRead);
          if (nRead <> SizeOf(Entry)) then
            exit;

          if (CompareName(Entry.Name)) then
          begin
            Result := GetIconData(Entry.Offset);
            exit;
          end;
        end;
      end;
    end;
  end;
end;

function TResourceFile.FindPEIcon ( szResourceID: PANSICHAR ): LONGINT;
var ResourceOffset : LONGINT;
    VirtualAddress : LONGINT;
    Directory      : TIMAGE_RESOURCE_DIRECTORY;
    Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
    nRead          : CARDINAL;
    nCount, nCount_1 : INTEGER;
    DataOfs        : LONGINT;

  procedure SeekData ( Offset: LONGINT );
  begin
    (* have to mask out the msb *)
    Seek(m_file, ResourceOffset + (Offset and not($80000000)));
  end;

  function CompareName ( Name: LONGINT ): BOOLEAN;
  var SavedPos   : LONGINT;
      NameLength : WORD;
      NameChar   : WORD;
      nRead      : INTEGER;
      szName     : PCHAR;
  begin
    (*
     * This function does a cheap comparison of ANSI and UNICODE
     * characters.. it should be exact as long as the image is
     * English..
     *)
    Result := FALSE;
    if (HIWORD(LONGINT(szResourceID)) = 0) then
    begin
      if (Name and $80000000 = 0) then
      begin
        if (Name and not($80000000) = LONGINT(szResourceID)) then
        begin
          Result := TRUE;
          exit;
        end;
      end;
    end else
    begin
      if (Name and $80000000 <> 0) then
      begin
        SavedPos := FilePos(m_file);

        SeekData(Name);

        BlockRead(m_file, NameLength, SizeOf(NameLength), nRead);
        if (nRead <> SizeOf(NameLength)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;

        (* validate that the name is the proper length *)
        if (NameLength <> StrLen(szResourceID)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;

        szName := szResourceID;
        BlockRead(m_file, NameChar, Sizeof(NameChar), nRead);
        if (nRead <> SizeOf(NameChar)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;
        while (BYTE(szName^) = NameChar) and
              (szName^ <> #0) do
        begin
          Inc(szName);

          BlockRead(m_file, NameChar, Sizeof(NameChar), nRead);
          if (nRead <> SizeOf(NameChar)) then
          begin
            Seek(m_File, SavedPos);
            exit;
          end;
        end;

        Result := (szName^ = #0);
        Seek(m_File, SavedPos);
      end;
    end;
  end;

  function GetIconData ( Offset: LONGINT ): LONGINT;
  var Directory      : TIMAGE_RESOURCE_DIRECTORY;
      Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
      Resource       : TIMAGE_RESOURCE_DATA_ENTRY;
      nRead          : CARDINAL;
  begin
    Result := 0;

    SeekData(Offset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* this always assumes the first entry is the correct icon *)
    (* this may not be the case if the icon has multiple versions or languages.. *)

    BlockRead(m_File, Entry, SizeOf(Entry), nRead);
    if (nRead <> SizeOf(Entry)) then
      exit;

    SeekData(Entry.Offset);

    BlockRead(m_File, Resource, SizeOf(Resource), nRead);
    if (nRead <> SizeOf(Resource)) then
      exit;

    Result := (Resource.OffsetToData - VirtualAddress) + ResourceOffset;
  end;

begin
  Result := 0;
  (* Find the offset to the .rsrc section *)
  ResourceOffset := ImageDirectoryOffset(IMAGE_DIRECTORY_ENTRY_RESOURCE, VirtualAddress);

  if (ResourceOffset <> 0) then
  begin
    Seek(m_File, ResourceOffset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* find the icon directory .. *)
    for nCount := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
    begin
      BlockRead(m_File, Entry, SizeOf(Entry), nRead);
      if (nRead <> SizeOf(Entry)) then
        exit;

      (* this doesn't bother checking if it's a directory pointer.. just assumes it is *)
      if (Entry.Name = LONGINT(RT_GROUPICON)) then
      begin
        SeekData(Entry.Offset);
        BlockRead(m_File, Directory, SizeOf(Directory), nRead);
        if (nRead <> SizeOf(Directory)) then
          exit;

        (* this could be a bit smarter to just to check the named or id'd entries *)
        for nCount_1 := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
        begin
          BlockRead(m_File, Entry, SizeOf(Entry), nRead);
          if (nRead <> SizeOf(Entry)) then
            exit;

          if (CompareName(Entry.Name)) then
          begin
            Result := GetIconData(Entry.Offset);
            exit;
          end;
        end;
      end;
    end;
  end;
end;

function TResourceFile.UpdateIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;
begin
  Result := FALSE;
  if (Assigned(szResourceID)) then
  begin
    (* Punt to the appropriate routine for the given file *)
    if (m_bPortable) then
      Result := UpdatePEIcon(szResourceID, szIcon)
    else
      Result := UpdateNEIcon(szResourceID, szIcon);
  end;
end;

function TResourceFile.UpdatePEIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;
var fileIcon : FILE;
    Header   : TFILE_ICON_HEADER;
    Icon     : TFILE_ICON_RESOURCE;
    nRead    : INTEGER;
    nCount   : INTEGER;
    IconData : LONGINT;
    SavedPos : LONGINT;
    Buffer   : PCHAR;    (* This is used as a standard buffer - strAlloc'd so I don't have to size it for free *)

  function FindResource: LONGINT;
  var GroupOffset : LONGINT;
      ResHeader   : TICON_HEADER;
      ResResource : TICON_RESOURCE;
      nRead       : INTEGER;
      nCount      : INTEGER;
  begin
    Result := 0;

    (* uses whatever is in the current Icon variable for a match *)
    GroupOffset := FindPEIcon(szResourceID);
    if (GroupOffset > 0) then
    begin
      Seek(m_File, GroupOffset);
      BlockRead(m_File, ResHeader, SizeOf(ResHeader), nRead);
      if (nRead <> SizeOf(ResHeader)) then
        exit;

      (* the INT typecast here is just in some really wierd case there are 0 icons.. *)
      for nCount := 0 to (INTEGER(ResHeader.wCount) - 1) do
      begin
        BlockRead(m_File, ResResource, SizeOf(ResResource), nRead);
        if (nRead <> SizeOf(ResResource)) then
          exit;


//IconProperty MOD !!!
//OLD
{        if (ResResource.bWidth = Icon.bWidth) and
           (ResResource.bHeight = Icon.bHeight) and
           (ResResource.bColorCount = Icon.bColorCount) then}
        if (ResResource.bWidth = Icon.bWidth) and
           (ResResource.bHeight = Icon.bHeight) then
        begin
          Result := GetPEIconDIB(MAKEINTRESOURCE(ResResource.wNameOrdinal));
          exit;
        end;
      end;
    end;
  end;

begin
  Result := FALSE;
  if (IOResult = 0) then;
  Assign(fileIcon, szIcon);
  Reset(fileIcon, 1);
  if (IOResult = 0) then
  begin
    BlockRead(fileIcon, Header, SizeOf(Header), nRead);
    if (nRead <> SizeOf(Header)) then
    begin
      Close(fileIcon);
      exit;
    end;

    for nCount := 0 to (Header.wCount - 1) do
    begin
      BlockRead(fileIcon, Icon, SizeOf(Icon), nRead);
      if (nRead <> SizeOf(Icon)) then
      begin
        Close(fileIcon);
        exit;
      end;

      IconData := FindResource;
      if (IconData <> 0) then
      begin
        SavedPos := FilePos(fileIcon);
        Seek(fileIcon, Icon.lImageOffset);

        Buffer := StrAlloc(Icon.lBytesInRes);
        if (Assigned(Buffer)) then
        begin
          (* assumes this read works *)
          BlockRead(fileIcon, Buffer^, Icon.lBytesInRes, nRead);

          Seek(m_file, IconData);
          BlockWrite(m_file, Buffer^, Icon.lBytesInRes);

          StrDispose(Buffer);
          Result := TRUE;
        end;

        Seek(fileIcon, SavedPos);
      end;
    end;

    Close(fileIcon);
  end;
end;

function TResourceFile.UpdateNEIcon ( szResourceID: PANSICHAR; szIcon: PANSICHAR ): BOOLEAN;
var fileIcon : FILE;
    Header   : TFILE_ICON_HEADER;
    Icon     : TFILE_ICON_RESOURCE;
    nRead    : INTEGER;
    nCount   : INTEGER;
    IconData : LONGINT;
    SavedPos : LONGINT;
    Buffer   : PCHAR;    (* This is used as a standard buffer - strAlloc'd so I don't have to size it for free *)

  function FindResource: LONGINT;
  var GroupOffset : LONGINT;
      ResHeader   : TICON_HEADER;
      ResResource : TICON_RESOURCE;
      nRead       : INTEGER;
      nCount      : INTEGER;
  begin
    Result := 0;

    (* uses whatever is in the current Icon variable for a match *)
    GroupOffset := FindNEIcon(szResourceID);
    if (GroupOffset > 0) then
    begin
      Seek(m_File, GroupOffset);
      BlockRead(m_File, ResHeader, SizeOf(ResHeader), nRead);
      if (nRead <> SizeOf(ResHeader)) then
        exit;

      (* the INT typecast here is just in some really wierd case there are 0 icons.. *)
      for nCount := 0 to (INTEGER(ResHeader.wCount) - 1) do
      begin
        BlockRead(m_File, ResResource, SizeOf(ResResource), nRead);
        if (nRead <> SizeOf(ResResource)) then
          exit;

        if (ResResource.bWidth = Icon.bWidth) and
           (ResResource.bHeight = Icon.bHeight) and
           (ResResource.bColorCount = Icon.bColorCount) then
        begin
          Result := GetNEIconDIB(MAKEINTRESOURCE(ResResource.wNameOrdinal));
          exit;
        end;
      end;
    end;
  end;

begin
  Result := FALSE;
  if (IOResult = 0) then;
  Assign(fileIcon, szIcon);
  Reset(fileIcon, 1);
  if (IOResult = 0) then
  begin
    BlockRead(fileIcon, Header, SizeOf(Header), nRead);
    if (nRead <> SizeOf(Header)) then
    begin
      Close(fileIcon);
      exit;
    end;

    for nCount := 0 to (Header.wCount - 1) do
    begin
      BlockRead(fileIcon, Icon, SizeOf(Icon), nRead);
      if (nRead <> SizeOf(Icon)) then
      begin
        Close(fileIcon);
        exit;
      end;

      IconData := FindResource;
      if (IconData <> 0) then
      begin
        SavedPos := FilePos(fileIcon);
        Seek(fileIcon, Icon.lImageOffset);

        Buffer := StrAlloc(Icon.lBytesInRes);
        if (Assigned(Buffer)) then
        begin
          (* assumes this read works *)
          BlockRead(fileIcon, Buffer^, Icon.lBytesInRes, nRead);

          Seek(m_file, IconData);
          BlockWrite(m_file, Buffer^, Icon.lBytesInRes);

          StrDispose(Buffer);
        end;

        Seek(fileIcon, SavedPos);
      end;
    end;

    Close(fileIcon);
  end;
end;

function TResourceFile.EnumPEIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;
var ResourceOffset : LONGINT;
    VirtualAddress : LONGINT;
    Directory      : TIMAGE_RESOURCE_DIRECTORY;
    Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
    nRead          : CARDINAL;
    nCount, nCount_1 : INTEGER;
    DataOfs        : LONGINT;

  procedure SeekData ( Offset: LONGINT );
  begin
    (* have to mask out the msb *)
    Seek(m_file, ResourceOffset + (Offset and not($80000000)));
  end;

  function CompareName ( Name: LONGINT ): BOOLEAN;
  var SavedPos   : LONGINT;
      NameLength : WORD;
      NameChar   : WORD;
      nRead      : INTEGER;
      nCount     : INTEGER;
      szName     : Array [ 0 .. 255 ] of CHAR;
  begin
    if (Name and $80000000 = 0) then
    begin
      (* Name is an ID *)

      (*
       * Construct name as a MAKEINTRESOURCE for the callback..
       *)
      Result := not(lpfnCallback(MAKEINTRESOURCE(Name and not($80000000))));
    end else
    begin
      (* Name is a lengthed UNICODE string *)
      SavedPos := FilePos(m_file);

      SeekData(Name);

      BlockRead(m_file, NameLength, SizeOf(NameLength), nRead);
      if (nRead <> SizeOf(NameLength)) then
      begin
        Seek(m_File, SavedPos);
        exit;
      end;

      for nCount := 0 to (INTEGER(NameLength) - 1) do
      begin
        BlockRead(m_File, NameChar, SizeOf(NameChar), nRead);
        if (nRead <> SizeOf(NameChar)) then
        begin
          Seek(m_File, SavedPos);
          exit;
        end;

        szName[nCount] := CHR(NameChar);
      end;

      szName[NameLength] := #0;

      Result := not(lpfnCallback(szName));

      Seek(m_File, SavedPos);
    end;
  end;

  function GetIconData ( Offset: LONGINT ): LONGINT;
  var Directory      : TIMAGE_RESOURCE_DIRECTORY;
      Entry          : TIMAGE_RESOURCE_DIRECTORY_ENTRY;
      Resource       : TIMAGE_RESOURCE_DATA_ENTRY;
      nRead          : CARDINAL;
  begin
    Result := 0;

    SeekData(Offset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* this always assumes the first entry is the correct icon *)
    (* this may not be the case if the icon has multiple versions or languages.. *)

    BlockRead(m_File, Entry, SizeOf(Entry), nRead);
    if (nRead <> SizeOf(Entry)) then
      exit;

    SeekData(Entry.Offset);

    BlockRead(m_File, Resource, SizeOf(Resource), nRead);
    if (nRead <> SizeOf(Resource)) then
      exit;

    Result := (Resource.OffsetToData - VirtualAddress) + ResourceOffset;
  end;

begin
  Result := FALSE;
  (* Find the offset to the .rsrc section *)
  ResourceOffset := ImageDirectoryOffset(IMAGE_DIRECTORY_ENTRY_RESOURCE, VirtualAddress);

  if (ResourceOffset <> 0) then
  begin
    Seek(m_File, ResourceOffset);
    BlockRead(m_File, Directory, SizeOf(Directory), nRead);
    if (nRead <> SizeOf(Directory)) then
      exit;

    (* find the icon directory .. *)
    for nCount := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
    begin
      BlockRead(m_File, Entry, SizeOf(Entry), nRead);
      if (nRead <> SizeOf(Entry)) then
        exit;

      (* assume everything worked at this point *)
      Result := TRUE;

      (* this doesn't bother checking if it's a directory pointer.. just assumes it is *)
      if (Entry.Name = LONGINT(RT_GROUPICON)) then
      begin
        SeekData(Entry.Offset);
        BlockRead(m_File, Directory, SizeOf(Directory), nRead);
        if (nRead <> SizeOf(Directory)) then
          exit;

        Result := TRUE;

        (* this could be a bit smarter to just to check the named or id'd entries *)
        for nCount_1 := 0 to (Directory.NumberOfNamedEntries + Directory.NumberOfIDEntries - 1) do
        begin
          BlockRead(m_File, Entry, SizeOf(Entry), nRead);
          if (nRead <> SizeOf(Entry)) then
            exit;

          (* CompareName returns the result of lpfnCallback *)
          if (CompareName(Entry.Name)) then
          begin
            exit;
          end;
        end;
      end;
    end;
  end;
end;

function TResourceFile.EnumNEIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;
var ResTable    : LONGINT;
    ResAlign    : WORD;

    ResType     : WORD;
    ResCount    : WORD;
    ResReserved : LONGINT;

    nCount      : INTEGER;

    ResOffset   : WORD;
    ResLength   : WORD;
    ResFlags    : WORD;
    ResID       : WORD;
    ResResd     : LONGINT;

  function CompareName ( Name: WORD ): BOOLEAN;
  var SavedPos  : LONGINT;
      nLen      : BYTE;
      NameChars : Array [ 0 .. 255 ] of CHAR;
  begin
    Result := FALSE;
    if (Name and $8000 = $8000) then
    begin
      Result := not(lpfnCallback(MAKEINTRESOURCE(Name and not($8000))));
    end else
    begin
      SavedPos := FilePos(m_File);

      Seek(m_File, ResTable + Name);
      BlockRead(m_File, nLen, SizeOf(nLen));
      BlockRead(m_File, NameChars, nLen);

      NameChars[nLen] := #0;
      Result := not(lpfnCallback(NameChars));

      Seek(m_file, SavedPos);
    end;
  end;

begin
  ResTable := LONGINT(m_MZHeader.e_lfanew) + m_NEHeader.ne_rsrctab;

  Seek(m_File, ResTable);
  BlockRead(m_File, ResAlign, SizeOf(ResAlign));

  BlockRead(m_File, ResType, SizeOf(ResType));
  BlockRead(m_File, ResCount, SizeOf(ResCount));
  BlockRead(m_File, ResReserved, SizeOf(ResReserved));

  while (ResType <> 0) do
  begin
    if (ResType and $8000 = $8000) and
       ((ResType and not ($8000)) = LONGINT(RT_GROUP_ICON)) then
    begin
      for nCount := 0 to (INTEGER(ResCount) - 1) do
      begin
        BlockRead(m_File, ResOffset, SizeOf(ResOffset));
        BlockRead(m_File, ResLength, SizeOf(ResLength));
        BlockRead(m_File, ResFlags, SizeOf(ResFlags));
        BlockRead(m_File, ResID, SizeOf(ResID));
        BlockRead(m_File, ResResd, SizeOf(ResResd));

        if (CompareName(ResID)) then
        begin
          break;
        end;
      end;
    end else
      Seek(m_File, FilePos(m_File) + ResCount * 12);

    BlockRead(m_File, ResType, SizeOf(ResType));
    BlockRead(m_File, ResCount, SizeOf(ResCount));
    BlockRead(m_File, ResReserved, SizeOf(ResReserved));
  end;
end;

function TResourceFile.EnumIcons ( lpfnCallback: TICONENUMERATOR ): BOOLEAN;
begin
  Result := FALSE;
  if (Assigned(lpfnCallback)) then
  begin
    (* Punt to the appropriate routine for the given file *)
    if (m_bPortable) then
      Result := EnumPEIcons(lpfnCallback)
    else
      Result := EnumNEIcons(lpfnCallback);
  end;
end;

function TResourceFile.UpdateIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile; szSourceID: PANSICHAR ): BOOLEAN;
begin
  Result := FALSE;
  if (Assigned(szResourceID)) and
     (Assigned(szSourceID)) then
  begin
    (* Punt to the appropriate routine for the given file *)
    if (m_bPortable) then
      Result := UpdatePEIconFromImage(szResourceID, ResFile, szSourceID)
    else
      Result := UpdateNEIconFromImage(szResourceID, ResFile, szSourceID);
  end;
end;

function TResourceFile.UpdatePEIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile;
                                               szSourceID: PANSICHAR ): BOOLEAN;
var GroupOffset : LONGINT;
    Header      : TICON_HEADER;
    Icon        : TICON_RESOURCE;
    nRead       : INTEGER;
    nCount      : INTEGER;
    SavedPos    : LONGINT;
    SourceDIB   : LONGINT;
    DestDIB     : LONGINT;
    srcBuffer   : PANSICHAR;

  function FindResource: LONGINT;
  var GroupOffset : LONGINT;
      ResHeader   : TICON_HEADER;
      ResResource : TICON_RESOURCE;
      nRead       : INTEGER;
      nCount      : INTEGER;
  begin
    Result := 0;

    (* uses whatever is in the current Icon variable for a match *)
    GroupOffset := FindPEIcon(szResourceID);
    if (GroupOffset > 0) then
    begin
      Seek(m_File, GroupOffset);
      BlockRead(m_File, ResHeader, SizeOf(ResHeader), nRead);
      if (nRead <> SizeOf(ResHeader)) then
        exit;

      (* the INT typecast here is just in some really wierd case there are 0 icons.. *)
      for nCount := 0 to (INTEGER(ResHeader.wCount) - 1) do
      begin
        BlockRead(m_File, ResResource, SizeOf(ResResource), nRead);
        if (nRead <> SizeOf(ResResource)) then
          exit;

        if (ResResource.bWidth = Icon.bWidth) and
           (ResResource.bHeight = Icon.bHeight) and
           (ResResource.bColorCount = Icon.bColorCount) then
        begin
          Result := GetPEIconDIB(MAKEINTRESOURCE(ResResource.wNameOrdinal));
          exit;
        end;
      end;
    end;
  end;

begin
  Result := FALSE;
  GroupOffset := ResFile.FindIcon(szSourceID);
  if (GroupOffset <> 0) then
  begin
    Seek(ResFile.m_File, GroupOffset);
    BlockRead(ResFile.m_File, Header, SizeOf(Header), nRead);
    if (nRead <> SizeOf(Header)) then
      exit;

    for nCount := 0 to (INTEGER(Header.wCount) - 1) do
    begin
      BlockRead(ResFile.m_File, Icon, SizeOf(Icon), nRead);
      if (nRead <> SizeOf(Icon)) then
        exit;

      SavedPos := FilePos(ResFile.m_File);

      DestDIB := FindResource;
      if (DestDIB <> 0) then
      begin
        Seek(m_File, DestDIB);
        SourceDIB := ResFile.GetIconDIB(MAKEINTRESOURCE(Icon.wNameOrdinal));
        if (SourceDIB <> 0) then
        begin
          Seek(ResFile.m_File, SourceDIB);
          srcBuffer := StrAlloc(Icon.lBytesInRes);
          BlockRead(ResFile.m_File, srcBuffer^, Icon.lBytesInRes);
          BlockWrite(m_File, srcBuffer^, Icon.lBytesInRes);
          StrDispose(srcBuffer);
        end;
      end;

      Seek(ResFile.m_File, SavedPos);
    end;

    Result := TRUE;
  end;
end;

function TResourceFile.UpdateNEIconFromImage ( szResourceID: PANSICHAR; ResFile: TResourceFile;
                                               szSourceID: PANSICHAR ): BOOLEAN;
var GroupOffset : LONGINT;
    Header      : TICON_HEADER;
    Icon        : TICON_RESOURCE;
    nRead       : INTEGER;
    nCount      : INTEGER;
    SavedPos    : LONGINT;
    SourceDIB   : LONGINT;
    DestDIB     : LONGINT;
    srcBuffer   : PANSICHAR;

  function FindResource: LONGINT;
  var GroupOffset : LONGINT;
      ResHeader   : TICON_HEADER;
      ResResource : TICON_RESOURCE;
      nRead       : INTEGER;
      nCount      : INTEGER;
  begin
    Result := 0;

    (* uses whatever is in the current Icon variable for a match *)
    GroupOffset := FindNEIcon(szResourceID);
    if (GroupOffset > 0) then
    begin
      Seek(m_File, GroupOffset);
      BlockRead(m_File, ResHeader, SizeOf(ResHeader), nRead);
      if (nRead <> SizeOf(ResHeader)) then
        exit;

      (* the INT typecast here is just in some really wierd case there are 0 icons.. *)
      for nCount := 0 to (INTEGER(ResHeader.wCount) - 1) do
      begin
        BlockRead(m_File, ResResource, SizeOf(ResResource), nRead);
        if (nRead <> SizeOf(ResResource)) then
          exit;

        if (ResResource.bWidth = Icon.bWidth) and
           (ResResource.bHeight = Icon.bHeight) and
           (ResResource.bColorCount = Icon.bColorCount) then
        begin
          Result := GetNEIconDIB(MAKEINTRESOURCE(ResResource.wNameOrdinal));
          exit;
        end;
      end;
    end;
  end;

begin
  Result := FALSE;
  GroupOffset := ResFile.FindIcon(szSourceID);
  if (GroupOffset <> 0) then
  begin
    Seek(ResFile.m_File, GroupOffset);
    BlockRead(ResFile.m_File, Header, SizeOf(Header), nRead);
    if (nRead <> SizeOf(Header)) then
      exit;

    for nCount := 0 to (INTEGER(Header.wCount) - 1) do
    begin
      BlockRead(ResFile.m_File, Icon, SizeOf(Icon), nRead);
      if (nRead <> SizeOf(Icon)) then
        exit;

      SavedPos := FilePos(ResFile.m_File);

      DestDIB := FindResource;
      if (DestDIB <> 0) then
      begin
        Seek(m_File, DestDIB);
        SourceDIB := ResFile.GetIconDIB(MAKEINTRESOURCE(Icon.wNameOrdinal));
        if (SourceDIB <> 0) then
        begin
          Seek(ResFile.m_File, SourceDIB);
          srcBuffer := StrAlloc(Icon.lBytesInRes);
          BlockRead(ResFile.m_File, srcBuffer^, Icon.lBytesInRes);
          BlockWrite(m_File, srcBuffer^, Icon.lBytesInRes);
          StrDispose(srcBuffer);
        end;
      end;

      Seek(ResFile.m_File, SavedPos);
    end;

    Result := TRUE;
  end;
end;

function TResourceFile.GetIconDIB ( szResourceID: PANSICHAR ): LONGINT;
begin
  (* Punt to the appropriate routine for the given file *)
  if (m_bPortable) then
    Result := GetPEIconDIB(szResourceID)
  else
    Result := GetNEIconDIB(szResourceID);
end;

destructor TResourceFile.Destroy;
begin
  (* make sure the file is open before we close it *)
  if (TFILEREC(m_file).mode <> fmClosed) then
    Close(m_file);
end;


end.
---------------------------------- end of "iconhckr.pas" ------------------------------------
0
 

Author Comment

by:DelFreak
ID: 6472730
bugroger,
Yes, I downloaded IconHack.zip. It didn't do much for me. I'll try your code.

Gwena, your code works fine. But as you said, it isn't 100% efficient. Let me try bugroger's code first. Thanks!


Everyone else, thank you for your help.
0
 
LVL 5

Expert Comment

by:Gwena
ID: 6472743
Hi delFreak :-)

Yup..my code works but..well... it still needs work
If I just had the time I think it could be tightened up to work pretty well... If anyone else wants to work on my code and make it better then just give them the points if it ends up being suitable for your tasks :-)

good luck...
0
 

Author Comment

by:DelFreak
ID: 6907595
burgroger, sorry it took so long. Been really busy. Thanks for your code. Worked well!

Gwena, thanks too!
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now