【编程】ICON – 从 DLL/EXE/ICL 中抽取图标(16 Bit ICL 文件的处理)

  一直以来用 AxIcon Workshop 来处理图标,但是 AxIcon Workshop稍微有点问题就是,不支持重复图标过滤,而且,在处理大量图标的时候很容易没有响应!:(


  为此,我自己写了一个图标处理工具,可以自动抽取 DLL/EXE/ICL 等文件中的图标,并进行重复图标自动过滤,图标扫描等功能,其中比较困难的是对 ICL 文件的处理,ICL 文件本质上是一个 16 Bit 的 DLL 资源文件,但是在 Windows 2000 下好象没有直接操作它的函数,至少我是不知道,查了 Google 也没查到相关资料,没有办法,只有硬来了,查了 16 Bit 的 EXE 的文件结构资料,结合网上可以找到的一些对16 Bit 的 EXE 的读写代码片段,再经过探索和摸索,终于成功的将从 ICL 中分离出 ICON 。其中的关键代码如下:希望给你有帮助


typedef UINT16          HANDLE16;
typedef HANDLE16       *LPHANDLE16;


DECLARE_HANDLE(FARPROC16);


#pragma pack( push )
#pragma pack( 2 )


typedef struct
{
    WORD     offset;
    WORD     length;
    WORD     flags;
    WORD     id;
    HANDLE16 handle;
    WORD     usage;
} NE_NAMEINFO;


typedef struct
{
    WORD        type_id;   /* Type identifier */
    WORD        count;     /* Number of resources of this type */
    FARPROC16   resloader; /* SetResourceHandler() */
    /*
     * Name info array.
     */
} NE_TYPEINFO;


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


// 图标目录
typedef struct
{
 WORD idReserved;   // Reserved (must be 0)
 WORD idType;    // Resource type (1 for icons)
 WORD idCount;   // How many images?
} GRPICONDIR, *LPGRPICONDIR;


// 图标项
typedef struct
{
 BYTE   bWidth;               // Width, in pixels, of the image
 BYTE   bHeight;              // Height, in pixels, of the image
 BYTE   bColorCount;          // Number of colors in image (0 if >=8bpp)
 BYTE   bReserved;            // Reserved
 WORD   wPlanes;              // Color Planes
 WORD   wBitCount;            // Bits per pixel
 DWORD  dwBytesInRes;         // how many bytes in this resource?
 WORD   nID;                  // the ID
} GRPNE_ICONDIRENTRY, *LPGRPNE_ICONDIRENTRY;


#pragma pack( pop )


#define NE_RT_CURSOR         0×8001
#define NE_RT_BITMAP         0×8002
#define NE_RT_ICON           0×8003
#define NE_RT_MENU           0×8004
#define NE_RT_DIALOG         0×8005
#define NE_RT_STRING         0×8006
#define NE_RT_FONTDIR        0×8007
#define NE_RT_FONT           0×8008
#define NE_RT_ACCELERATOR    0×8009
#define NE_RT_RCDATA         0x800a
#define NE_RT_GROUP_CURSOR   0x800c
#define NE_RT_GROUP_ICON     0x800e


// ICL 图标枚举
HRESULT ICL_EnumResourceNames(IN CONST HANDLE hFile, IN UINT nType, IN NE_ENUM_RES_NAME_PROC pFunc, IN LPARAM lParam)
{
 DWORD dwRead = 0;


 // 读区 DOS 文件头
 IMAGE_DOS_HEADER oDOSHeader;
 if(!::ReadFile( hFile, &oDOSHeader, sizeof(IMAGE_DOS_HEADER), &dwRead, NULL ) )
 {
  return ::GetLastError();
 }
 
 // 读区 NE 文件头
 IMAGE_OS2_HEADER oNEHeader;
 ::SetFilePointer(hFile, oDOSHeader.e_lfanew, NULL, FILE_BEGIN);
  if(!::ReadFile( hFile, &oNEHeader, sizeof(IMAGE_OS2_HEADER), &dwRead, NULL ) )
 {
  return ::GetLastError();
 }


  // 读区 RSRC 资源表
 DWORD nPos = oDOSHeader.e_lfanew + oNEHeader.ne_rsrctab;
 ::SetFilePointer(hFile, nPos, NULL, FILE_BEGIN);


 WORD nSizeShift;
  if(!::ReadFile( hFile, &nSizeShift, sizeof(WORD), &dwRead, NULL ) )
 {
  return ::GetLastError();
 }


    NE_TYPEINFO oInfo;
  if(!::ReadFile( hFile, &oInfo, sizeof(NE_TYPEINFO), &dwRead, NULL ) )
 {
  return ::GetLastError();
 }


 // 枚举所有的资源
 DWORD nPosEnd  = oDOSHeader.e_lfanew + oNEHeader.ne_restab;
 DWORD nPosName = nPosEnd + 4;


 NE_NAMEINFO oName;
 UINT nIndex = 0;
 while (oInfo.type_id != 0 && nPos < nPosEnd)
    {
        for (UINT nCount = oInfo.count; nCount > 0; nCount–)
        {
    if(!::ReadFile(hFile, &oName, sizeof(NE_NAMEINFO), &dwRead, NULL))
   {
    return ::GetLastError();
   }
   if(oInfo.type_id == nType)
   {
    // 保存文件位置
    DWORD nPosOld = ::SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
    
    // 资源名
    BYTE nSize;
    ::SetFilePointer(hFile, nPosName, NULL, FILE_BEGIN);
     if(!::ReadFile( hFile, &nSize, sizeof(BYTE), &dwRead, NULL))
    {
     return ::GetLastError();
    }
    if(nSize > 255) return E_FAIL;


    nPosName += sizeof(BYTE) + nSize;


    ACHAR sName[255 + 1];
     if(!::ReadFile( hFile, sName, nSize, &dwRead, NULL))
    {
     return ::GetLastError();
    }
    if(nSize == 1 && sName[0] == __A(
‘@’)) nSize = 0;
    sName[nSize] = ACHR_NULL;


    // 资源组
    GRPICONDIR oDir;
    DWORD nPosGroup = oName.offset << nSizeShift;
    ::SetFilePointer(hFile, nPosGroup, NULL, FILE_BEGIN);
     if(!::ReadFile( hFile, &oDir, sizeof(GRPICONDIR), &dwRead, NULL))
    {
     return ::GetLastError();
    }


    // 处理
    STK_CONVERSIONU;
    pFunc(hFile, nIndex++, STK_A2T(sName), &oDir, lParam);


    // 恢复文件位置
    ::SetFilePointer(hFile, nPosOld, NULL, FILE_BEGIN);
   }
        }
   if(!::ReadFile( hFile, &oInfo, sizeof(NE_TYPEINFO), &dwRead, NULL))
  {
   return ::GetLastError();
  }
    }
 return S_OK;
}

This entry was posted in [P]编程技术. Bookmark the permalink.

One Response to 【编程】ICON – 从 DLL/EXE/ICL 中抽取图标(16 Bit ICL 文件的处理)

  1. Linux says:

    界面

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word