Win32 二进制资源格式(续三)

    技术2022-05-11  68

    3.资源头格式 整个文件的格式实际上只是一些资源文件项简单的连接到了一起。每个资源都包含一个单独的资源信息(比如一个对话框或一个字符串表)。 每个项都由一个资源头和其后的资源数据组成。一个资源头(双字对齐的)由4个元素组成:两个表示资源头和资源数据大小的双字、一个资源类型、一个资源名称,还可能有一些附加的资源信息。资源的数据跟在资源头后面,每种资源类型有其自己的数据格式。 3.1 DataSize 这个域给出了跟在资源头后面的数据的大小(不包括在此资源与后面的任何资源之间的填充数据(编者:也就是说这是此资源的实际大小))。 3.2 HeaderSize HeaderSize域给出了资源头结构的大小。 3.3 Type Type域要么是一个数字,要么是一个指向表示类型名称的以空值结尾的UNICODE字符串。这个可变的类型被称为“名称或序数”(Name or Ordinal)域,它经常出现在资源文件中ID出现的地方。 名称或序数域的第一个单字域标志出这个域到底是一个数字还是一个字符串。如果它等于0xffff(一个非法UNICODE字符),那么在它后面的单字信息就是一个类型序号(一个数字)。否则,这个域就是一个UNICODE字符串。 如果类型域是一个数字,那它就代表一个标准的或者用户自定义的资源类型。所有标准的Windows 资源类型都被赋予一个特定值,如下表所示。这个表摘自用来生成RC(资源编译器)的头文件,它包含了绝大多数资源类型的类型序数:     /*预定义的资源类型*/     #define    RT_NEWRESOURCE        0x2000     #define    RT_ERROR            0x7fff     #define    RT_CURSOR            1     #define    RT_BITMAP            2     #define    RT_ICON                3     #define    RT_MENU                4     #define    RT_DIALOG            5     #define    RT_STRING            6     #define    RT_FONTDIR            7     #define    RT_FONT                8     #define    RT_ACCELERATORS        9     #define    RT_RCDATA            10     #define    RT_MESSAGETABLE        11     #define    RT_GROUP_CURSOR        12     #define    RT_GROUP_ICON        14     #define    RT_VERSION            16     #define    RT_NEWBITMAP        (RT_BITMAP | RT_NEWRESOURCE)     #define    RT_NEWMENU            (RT_MENU | RT_NEWRESOURCE)     #define    RT_NEWDIALOG        (RT_DIALOG | RT_NEWRESOURCE) 如果类型域是一个字符串,那么这个类型是一个用户自定义的类型。 3.4 Names 名称域标识了每一个资源。根类型域一样,名称域也是一个数字或者一个字符串,区分方法也跟类型域一样。 注意:在类型域和名称域之间不需要填充(双字对齐),由于它们只包含单字数据,名称域将总是自动对齐。不过在名称域之后可能会有一个单字填充,使余下的资源头能够双字对齐。 3.5 附加头信息 附加信息包含更多的关于资源数据的信息,包括大小和语言ID。包含附加信息的资源头结构如下所示: struct tagResource {     DWORD    DataSize;            //不包含头结构的资源数据的大小     DWORD    HeaderSize;            //附加头的长度     [类型序号或字符串]            //类型标识,id或字符串     [名称序号或字符串]            //名称标识,id或字符串     DWORD    DataVersion;        //预定义的资源数据版本     WORD    MemoryFalgs;        //资源状态     WORD    LanguageId;            //对NLS的UNICODE支持     DWORD    Version;            //资源数据的版本     DWORD    Characteristics;    //数据的特征     }; 附加信息结构总是从资源文件中双字对齐的地方开始,因此在名称域与ResAdditional结构之间可能会有一些填充数据。 3.5.1 DataVersion DataVersion域用来检查资源头里后跟的数据信息的格式。这可能会在将来用来将附加信息输入到预定义格式中去。 3.5.2 MemoryFlags wMemoryFlags域解释一个给定资源的状态。这些属性通过在.RC脚本中添加标志来给定。脚本标志包含以下标志值:     #define    MOVEABLE        0x0010     #define    FIXED            ~MOVEABLE     #define    PURE            0x0020     #define    IMPURE            ~PURE     #define    PRELOAD            0x0040     #define    LOADONCALL        ~PRELOAD     #define    DISCARDABLE        0x1000 NT系统的资源编译器总是忽略MOVEABLE、IMPURE和PRELOAD标志。 3.5.3 LanguageId 语言ID包含在每个资源中,用来指定字符串的语言,当它们需要被翻译回单字节字符串时,将会需要这些信息。因此,可能会有多种资源拥有相同的类型和名称等,但仅仅语言不同。 NLS规范的附录A中有语言ID的相关文档,winnt.h中也有。资源的语言由LANGUAGE语句指定。 3.5.4 Version和Characteristics 当前的资源文件格式中也包含版本和特征域。它们分别由VERSION和CHARACTERISTICS域指定。 3.6 区分16位和32位资源文件 软件开发商可能会开发一些同时支持16位和32位资源文件的资源读写工具,微软为此提供了一个方法:使用非法的类型和名称序数值来区分。 方法是在资源文件中放置一个非法资源。微软选择了以下八个字节:     0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x00 假设资源文件是16位的。此时类型域是非法的,因为第一个字节告诉我们它是一个字符串,但一个0长度的字符串是非法的。因此这是一个非法的16位资源头,也就是说这个文件是32位的。 假设资源文件是32位的。由上可知数据的大小为0,当然不可能有这种情况。 Windows 32资源编译器在每个32位资源文件中前置这几个字节的数据(后跟的是一个附加数据结构,描述一个长度为0、类型序数为0、名称序数为0的资源),用来区分16位和32位资源文件。任何想要读取资源文件的工具都应忽略这个资源。 3.7 文件对齐 有时,将资源分开到几个脚本中、分开编译这些资源文件,最后将它们合并起来会很有用,因此很有必要指出资源文件都是填充到双字大小的。如果不包括这个填充,可能会导致文件中的资源不能双字对齐。  

    最新回复(0)