[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnet/image winres_reader.c,NONE,1.1 Makefile
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnet/image winres_reader.c,NONE,1.1 Makefile.am,1.15,1.16 image.h,1.27,1.28 pecoff_loader.c,1.14,1.15 |
Date: |
Mon, 07 Jul 2003 08:44:53 -0400 |
Update of /cvsroot/dotgnu-pnet/pnet/image
In directory subversions:/tmp/cvs-serv1790/image
Modified Files:
Makefile.am image.h pecoff_loader.c
Added Files:
winres_reader.c
Log Message:
Add code to "image" to read the contents of the ".rsrc" section in an IL binary.
--- NEW FILE ---
/*
* winres_reader.c - Read the data in the ".rsrc" section of an IL binary.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "image.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Information about a resource entry.
*/
typedef struct _tagILResourceEntry ILResourceEntry;
struct _tagILResourceEntry
{
int isDirectory;
char *name;
int nameLen;
ILResourceEntry *children;
ILResourceEntry *next;
unsigned char *data;
unsigned long length;
};
/*
* Information about the resource section.
*/
struct _tagILResourceSection
{
ILImage *image;
unsigned char *data;
unsigned long length;
ILResourceEntry *rootDirectory;
};
/*
* Length-delimited string comparison with ignore case.
*/
static int StrNICmp(const char *str1, const char *str2, int len)
{
char ch1;
char ch2;
while(len > 0 && *str1 != '\0' && *str2 != '\0')
{
ch1 = *str1++;
if(ch1 >= 'A' && ch1 <= 'Z')
{
ch1 = (ch1 - 'A' + 'a');
}
ch2 = *str2++;
if(ch2 >= 'A' && ch2 <= 'Z')
{
ch2 = (ch2 - 'A' + 'a');
}
if(ch1 < ch2)
{
return -1;
}
else if(ch1 > ch2)
{
return 1;
}
--len;
}
if(!len)
{
return 0;
}
if(*str1 != '\0')
{
return 1;
}
else if(*str2 != '\0')
{
return -1;
}
else
{
return 0;
}
}
/*
* Read the name of a resource from the resource section.
*/
static char *ReadResourceName(ILResourceSection *section, unsigned long offset)
{
ILUInt32 slen;
ILUInt32 index;
char *name;
/* Read the length of the Unicode string */
if(offset >= section->length || (offset + 2) > section->length)
{
return ILDupString("");
}
slen = IL_READ_UINT16(section->data + offset);
if((section->length - (offset + 2)) < (slen * 2))
{
return ILDupString("");
}
/* Convert the string from Unicode into ASCII. We use a simple
conversion algorithm because the tag names will almost always
be simple ASCII names. Change to UTF8 later if necessary */
name = (char *)ILMalloc(slen + 1);
if(!name)
{
return 0;
}
for(index = 0; index < slen; ++index)
{
name[index] = (char)(section->data[offset + 2 + index * 2]);
}
name[slen] = 0;
return name;
}
/*
* Convert a resource number into a name.
*/
static char *ResourceNumberToName(unsigned long number)
{
char buffer[64];
sprintf(buffer, "%ld", number);
return ILDupString(buffer);
}
/*
* Free a resource entry and all of its children.
*/
static void FreeResourceEntry(ILResourceEntry *entry)
{
ILResourceEntry *current, *next;
if(entry->name)
{
ILFree(entry->name);
}
current = entry->children;
while(current != 0)
{
next = current->next;
FreeResourceEntry(current);
current = next;
}
ILFree(entry);
}
/*
* Parse the contents of a resource data entry.
*/
static ILResourceEntry *ParseResourceEntry
(ILResourceSection *section, unsigned long offset, char
*name)
{
ILResourceEntry *entry;
unsigned long rva;
unsigned long length;
/* Allocate a structure to hold the entry's contents */
if((entry = (ILResourceEntry *)ILMalloc(sizeof(ILResourceEntry))) == 0)
{
if(name)
{
ILFree(name);
}
return 0;
}
entry->isDirectory = 0;
entry->name = name;
entry->nameLen = strlen(name);
entry->children = 0;
entry->next = 0;
entry->data = 0;
entry->length = 0;
/* Parse the resource data entry */
if(offset >= section->length || (offset + 16) >= section->length)
{
return entry;
}
rva = IL_READ_UINT32(section->data + offset);
length = IL_READ_UINT32(section->data + offset + 4);
/* Validate the entry information */
if(rva >= section->length || length > section->length ||
rva > (section->length - length))
{
return entry;
}
/* Record the location of the resource's data */
entry->data = section->data + rva;
entry->length = length;
return entry;
}
/*
* Parse the contents of a resource directory.
*/
static ILResourceEntry *ParseResourceDirectory
(ILResourceSection *section, unsigned long offset, char
*name)
{
ILResourceEntry *dir;
ILResourceEntry *entry;
ILResourceEntry *last;
ILUInt32 numNamedEntries;
ILUInt32 numIdEntries;
unsigned long rva;
/* Allocate a structure to hold the directory's contents */
if((dir = (ILResourceEntry *)ILMalloc(sizeof(ILResourceEntry))) == 0)
{
if(name)
{
ILFree(name);
}
return 0;
}
dir->isDirectory = 1;
dir->name = name;
dir->children = 0;
dir->next = 0;
dir->data = 0;
dir->length = 0;
/* Parse the header for the resource directory table */
if(offset >= section->length || (offset + 16) >= section->length)
{
return dir;
}
numNamedEntries = IL_READ_UINT16(section->data + offset + 12);
numIdEntries = IL_READ_UINT16(section->data + offset + 14);
offset += 16;
/* Process the named directory entries */
last = 0;
while(numNamedEntries > 0)
{
if(offset > (section->length - 8))
{
break;
}
name = ReadResourceName
(section, IL_READ_UINT32(section->data + offset));
if(!name)
{
FreeResourceEntry(dir);
return 0;
}
rva = IL_READ_UINT32(section->data + offset + 4);
if((rva & (unsigned long)0x80000000) != 0)
{
/* Process a sub-directory */
rva &= (unsigned long)0x7FFFFFFF;
entry = ParseResourceDirectory(section, rva, name);
}
else
{
/* Process a regular data entry */
entry = ParseResourceEntry(section, rva, name);
}
if(!entry)
{
FreeResourceEntry(dir);
return 0;
}
if(last)
{
last->next = entry;
}
else
{
dir->children = entry;
}
last = entry;
offset += 8;
--numNamedEntries;
}
/* Process the identifier-based directory entries */
while(numIdEntries > 0)
{
if(offset > (section->length - 8))
{
break;
}
name = ResourceNumberToName(IL_READ_UINT32(section->data +
offset));
if(!name)
{
FreeResourceEntry(dir);
return 0;
}
rva = IL_READ_UINT32(section->data + offset + 4);
if((rva & (unsigned long)0x80000000) != 0)
{
/* Process a sub-directory */
rva &= (unsigned long)0x7FFFFFFF;
entry = ParseResourceDirectory(section, rva, name);
}
else
{
/* Process a regular data entry */
entry = ParseResourceEntry(section, rva, name);
}
if(!entry)
{
FreeResourceEntry(dir);
return 0;
}
if(last)
{
last->next = entry;
}
else
{
dir->children = entry;
}
last = entry;
offset += 8;
--numIdEntries;
}
/* Return the completed directory to the caller */
return dir;
}
ILResourceSection *ILResourceSectionCreate(ILImage *image)
{
ILResourceSection *section;
/* Allocate space for the section information */
if((section = (ILResourceSection *)ILMalloc(sizeof(ILResourceSection)))
== 0)
{
return 0;
}
/* Initialize the section information */
section->image = image;
if(!ILImageGetSection(image, IL_SECTION_WINRES,
(void **)&(section->data),
&(section->length)))
{
section->data = 0;
section->length = 0;
}
/* Parse the directory structure */
section->rootDirectory = ParseResourceDirectory(section, 0, 0);
if(!(section->rootDirectory))
{
ILFree(section);
return 0;
}
/* Return the section information to the caller */
return section;
}
void ILResourceSectionDestroy(ILResourceSection *section)
{
if(section)
{
if(section->rootDirectory)
{
FreeResourceEntry(section->rootDirectory);
}
ILFree(section);
}
}
static ILResourceEntry *FindEntry(ILResourceSection *section, const char *name)
{
ILResourceEntry *entry;
int posn;
/* Search down the hierarchy for the specified entry */
entry = section->rootDirectory;
while(entry != 0)
{
if(*name == '/')
{
++name;
continue;
}
else if(*name == '\0')
{
break;
}
posn = 0;
while(name[posn] != '\0' && name[posn] != '/')
{
++posn;
}
entry = entry->children;
while(entry != 0)
{
if(entry->nameLen == posn &&
!StrNICmp(entry->name, name, posn))
{
break;
}
entry = entry->next;
}
name += posn;
}
/* Return the result to the caller */
return entry;
}
void *ILResourceSectionGetEntry(ILResourceSection *section, const char *name,
unsigned long
*length)
{
ILResourceEntry *entry;
/* Validate the parameters */
if(!section || !name || !length)
{
if(length)
{
*length = 0;
}
return 0;
}
/* Search down the hierarchy for the specified entry */
entry = FindEntry(section, name);
/* Return the result to the caller */
if(entry && !(entry->isDirectory))
{
*length = entry->length;
return entry->data;
}
else
{
*length = 0;
return 0;
}
}
void *ILResourceSectionGetFirstEntry(ILResourceSection *section,
const
char *name, unsigned long *length)
{
ILResourceEntry *entry;
/* Validate the parameters */
if(!section || !name || !length)
{
if(length)
{
*length = 0;
}
return 0;
}
/* Search down the hierarchy for the specified entry */
entry = FindEntry(section, name);
/* Find the first leaf node under the entry */
while(entry != 0 && entry->children != 0)
{
entry = entry->children;
}
/* Return the result to the caller */
if(entry && !(entry->isDirectory))
{
*length = entry->length;
return entry->data;
}
else
{
*length = 0;
return 0;
}
}
#ifdef __cplusplus
};
#endif
Index: Makefile.am
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/image/Makefile.am,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -r1.15 -r1.16
*** Makefile.am 18 Feb 2003 05:25:08 -0000 1.15
--- Makefile.am 7 Jul 2003 12:44:50 -0000 1.16
***************
*** 39,42 ****
--- 39,43 ----
synthetic.c \
uncompress.c \
+ winres_reader.c \
writer.c
Index: image.h
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/image/image.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -C2 -r1.27 -r1.28
*** image.h 22 Jun 2003 01:20:35 -0000 1.27
--- image.h 7 Jul 2003 12:44:50 -0000 1.28
***************
*** 179,182 ****
--- 179,184 ----
unsigned long tlsRVA; /* RVA for the start of ".tls"
*/
unsigned long tlsSize; /* Size of ".tls" */
+ unsigned long rsrcRVA; /* RVA for the start of ".rsrc"
*/
+ unsigned long rsrcSize; /* Size of ".rsrc" */
/* Memory stack that is used to allocate program objects */
Index: pecoff_loader.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/image/pecoff_loader.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -r1.14 -r1.15
*** pecoff_loader.c 15 May 2003 04:51:47 -0000 1.14
--- pecoff_loader.c 7 Jul 2003 12:44:50 -0000 1.15
***************
*** 191,194 ****
--- 191,196 ----
unsigned long tlsRVA;
unsigned long tlsSize;
+ unsigned long rsrcRVA;
+ unsigned long rsrcSize;
ILSectionMap *map;
ILSectionMap *newMap;
***************
*** 346,349 ****
--- 348,353 ----
tlsRVA = 0;
tlsSize = 0;
+ rsrcRVA = 0;
+ rsrcSize = 0;
while(numSections > 0)
{
***************
*** 415,418 ****
--- 419,427 ----
tlsSize = newMap->virtSize;
}
+ else if(!ILMemCmp(buffer, ".rsrc\0\0\0", 8))
+ {
+ rsrcRVA = newMap->virtAddr;
+ rsrcSize = newMap->virtSize;
+ }
if(newMap->realSize > 0)
{
***************
*** 629,632 ****
--- 638,643 ----
(*image)->tlsRVA = tlsRVA;
(*image)->tlsSize = tlsSize;
+ (*image)->rsrcRVA = rsrcRVA;
+ (*image)->rsrcSize = rsrcSize;
/* Load the meta information from the image */
***************
*** 1070,1073 ****
--- 1081,1092 ----
*address = image->tlsRVA;
*size = image->tlsSize;
+ }
+ break;
+
+ case IL_SECTION_WINRES:
+ {
+ /* Windows resource section */
+ *address = image->rsrcRVA;
+ *size = image->rsrcSize;
}
break;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnet/image winres_reader.c,NONE,1.1 Makefile.am,1.15,1.16 image.h,1.27,1.28 pecoff_loader.c,1.14,1.15,
Rhys Weatherley <address@hidden> <=