📄 exerespe.c
字号:
static RcStatus traverseTree( PEResDir * dir, void * visit_data,
RcStatus (*visit)( PEResEntry *, void * visit_data ) )
/*******************************************************************/
/* Perfroms a level order traversal of a PEResDir tree calling visit at */
/* each entry */
{
PEResEntry * curr_entry;
PEResEntry * last_child;
PEResDirEntry * curr_dir;
DirEntryQueue queue;
RcStatus ret;
QueueInit( &queue );
QueueAdd( &queue, &dir->Root );
while( !QueueIsEmpty( &queue ) ) {
curr_dir = QueueRemove( &queue );
last_child = curr_dir->Children + curr_dir->Head.num_name_entries +
curr_dir->Head.num_id_entries;
curr_entry = curr_dir->Children;
while( curr_entry < last_child ) {
ret = visit( curr_entry, visit_data );
if( ret != RS_OK ) return( ret );
if( curr_entry->IsDirEntry ) {
QueueAdd( &queue, &curr_entry->u.Dir );
}
curr_entry++;
}
}
QueueEmpty( &queue );
return( RS_OK );
} /* traverseTree */
static RcStatus SetEntryOffset( PEResEntry * entry, void * _curr_offset )
/***********************************************************************/
{
int num_entries;
uint_32 *curr_offset = _curr_offset;
if( entry->IsDirEntry ) {
entry->Entry.entry_rva = *curr_offset | PE_RESOURCE_MASK_ON;
num_entries = entry->u.Dir.Head.num_name_entries +
entry->u.Dir.Head.num_id_entries;
*curr_offset += sizeof(resource_dir_header) +
num_entries * sizeof(resource_dir_entry);
} else {
entry->Entry.entry_rva = *curr_offset;
*curr_offset += sizeof(resource_entry);
}
return( RS_OK );
} /* SetEntryOffset */
static RcStatus AdjustNameEntry( PEResEntry * entry, void * _dir_size )
/*********************************************************************/
{
uint_32 str_offset;
uint_32 *dir_size = _dir_size;
if( entry->Entry.id_name & PE_RESOURCE_MASK_ON ) {
/* the id_name contains the offset into the string block */
str_offset = entry->Entry.id_name & PE_RESOURCE_MASK;
str_offset += *dir_size;
entry->Entry.id_name = str_offset | PE_RESOURCE_MASK_ON;
}
return( RS_OK );
} /* AdjustNameEntry */
static int ComparePEResIdName( const void * _entry1,
const void * _entry2 )
/***********************************************************************/
{
const PEResEntry * entry1 = _entry1;
const PEResEntry * entry2 = _entry2;
if( entry1->Name == NULL ) {
if( entry2->Name == NULL ) {
if( entry1->Entry.id_name > entry2->Entry.id_name ) {
return( 1 );
} else if( entry1->Entry.id_name < entry2->Entry.id_name ) {
return( -1 );
} else {
return( 0 );
}
} else {
return( 1 );
}
} else {
if( entry2->Name == NULL ) {
return( -1 );
} else {
return( CompareStringItems32( entry1->Name, entry2->Name ) );
}
}
} /* ComparePEResIdName */
static RcStatus SortDirEntry( PEResEntry * entry, void * dummy )
/*********************************************************/
{
int num_entries;
dummy = dummy;
if( entry->IsDirEntry ) {
num_entries = entry->u.Dir.Head.num_name_entries +
entry->u.Dir.Head.num_id_entries;
qsort( entry->u.Dir.Children, num_entries, sizeof(PEResEntry),
ComparePEResIdName );
}
return( RS_OK );
} /* SortDirEntry */
static void CompleteTree( PEResDir * dir )
/****************************************/
{
uint_32 curr_offset;
int num_entries;
num_entries = dir->Root.Head.num_name_entries +
dir->Root.Head.num_id_entries;
/* sort the entries at each level */
qsort( dir->Root.Children, num_entries, sizeof(PEResEntry),
ComparePEResIdName );
traverseTree( dir, NULL, SortDirEntry );
/* Set curr_offset to the size of the root entry */
curr_offset = sizeof(resource_dir_header) +
num_entries * sizeof(resource_dir_entry);
traverseTree( dir, &curr_offset, SetEntryOffset );
dir->DirSize = curr_offset;
traverseTree( dir, &curr_offset, AdjustNameEntry );
} /* CompleteTree */
typedef struct CopyResInfo {
int to_handle;
ExeFileInfo *file; // for setting debugging offset
ResFileInfo *curres;
ResFileInfo *errres;
} CopyResInfo;
/*
* copyDataEntry
* NB when an error occurs this function MUST return without altering errno
*/
static RcStatus copyDataEntry( PEResEntry *entry, void *_copy_info )
/******************************************************************/
{
CopyResInfo *copy_info = _copy_info;
WResLangInfo *res_info;
long seek_rc;
uint_32 diff;
RcStatus status;
ResFileInfo *info;
int closefile;
closefile = FALSE;
if( !entry->IsDirEntry ) {
info = WResGetFileInfo( entry->u.Data.Wind );
if( copy_info->curres == NULL || copy_info->curres == info ) {
res_info = WResGetLangInfo( entry->u.Data.Wind );
seek_rc = RcSeek( info->Handle, res_info->Offset, SEEK_SET );
if( seek_rc == -1 ) return( RS_READ_ERROR );
status = CopyExeData( info->Handle, copy_info->to_handle,
res_info->Length );
if( status != RS_OK ) {
copy_info->errres = info;
return( status );
}
diff = ALIGN_VALUE( res_info->Length, sizeof(uint_32) );
if( diff != res_info->Length ) {
/* add the padding */
// seek_rc = RcSeek( copy_info->to_handle, diff - res_info->Length,
// SEEK_CUR );
RcPadFile( copy_info->to_handle, diff - res_info->Length );
if( seek_rc == -1 ) return( RS_WRITE_ERROR );
}
CheckDebugOffset( copy_info->file );
}
}
return( RS_OK );
} /* copyDataEntry */
/*
* copyPEResources
* NB when an error occurs this function MUST return without altering errno
*/
static RcStatus copyPEResources( ExeFileInfo * tmp, ResFileInfo *resfiles,
int to_handle, int writebyfile,
ResFileInfo **errres )
/****************************************************************/
{
CopyResInfo copy_info;
PEExeInfo * info;
pe_va start_rva;
uint_32 start_off;
long seek_rc;
RcStatus ret;
int tmpopened;
info = &tmp->u.PEInfo;
start_rva = info->Res.ResRVA + info->Res.DirSize +
info->Res.String.StringBlockSize;
start_off = info->Res.ResOffset + info->Res.DirSize +
info->Res.String.StringBlockSize;
copy_info.to_handle = to_handle;
copy_info.errres = NULL;
copy_info.file = tmp; /* for tracking debugging info offset */
start_off = ALIGN_VALUE( start_off, sizeof(uint_32) );
seek_rc = RcSeek( to_handle, start_off, SEEK_SET );
if( seek_rc == -1 ) return( RS_WRITE_ERROR );
if( !writebyfile ) {
copy_info.curres = NULL;
ret = traverseTree( &info->Res, ©_info, copyDataEntry );
*errres = copy_info.errres;
} else {
ret = RS_OK;
while( resfiles != NULL ) {
copy_info.curres = resfiles;
if( resfiles->IsOpen ) {
tmpopened = FALSE;
} else {
resfiles->Handle = ResOpenFileRO( resfiles->name );
if( resfiles->Handle == -1 ) {
ret = RS_OPEN_ERROR;
*errres = resfiles;
break;
}
resfiles->IsOpen = TRUE;
tmpopened = TRUE;
}
ret = traverseTree( &info->Res, ©_info, copyDataEntry );
if( tmpopened ) {
ResCloseFile( resfiles->Handle );
resfiles->Handle = -1;
resfiles->IsOpen = FALSE;
}
if( ret != RS_OK ) {
*errres = resfiles;
break;
}
resfiles = resfiles->next;
}
}
return( ret );
} /* copyPEResources */
/*
* writeDirEntry -
* NB when an error occurs this function MUST return without altering errno
*/
static RcStatus writeDirEntry( PEResDirEntry *entry, int handle )
/***************************************************************/
{
int num_wrote;
int child_num;
num_wrote = RcWrite( handle, &entry->Head, sizeof(resource_dir_header) );
if( num_wrote != sizeof(resource_dir_header) ) return( RS_WRITE_ERROR );
for( child_num = 0; child_num < entry->Head.num_name_entries +
entry->Head.num_id_entries; child_num++ ) {
num_wrote = RcWrite( handle, entry->Children + child_num,
sizeof(resource_dir_entry) );
if( num_wrote != sizeof(resource_dir_entry) ) return( RS_WRITE_ERROR );
}
return( RS_OK );
} /* writeDirEntry */
/*
* writeDataEntry -
* NB when an error occurs this function MUST return without altering errno
*/
static int writeDataEntry( PEResDataEntry * entry, int handle )
/*************************************************************/
{
int num_wrote;
num_wrote = RcWrite( handle, &entry->Entry, sizeof(resource_entry) );
if( num_wrote != sizeof(resource_entry) ) return( RS_WRITE_ERROR );
return( RS_OK );
} /* writeDataEntry */
typedef struct {
ResFileInfo *curfile;
unsigned_32 *rva;
} DataEntryCookie;
/*
* setDataEntry
*/
static RcStatus setDataEntry( PEResEntry *entry, void *_info )
/************************************************************/
{
WResLangInfo *langinfo;
ResFileInfo *fileinfo;
DataEntryCookie *info = _info;
if( !entry->IsDirEntry ) {
fileinfo = WResGetFileInfo( entry->u.Data.Wind );
if( info->curfile == NULL || info->curfile == fileinfo ) {
langinfo = WResGetLangInfo( entry->u.Data.Wind );
entry->u.Data.Entry.data_rva = *info->rva;
entry->u.Data.Entry.size = langinfo->Length;
entry->u.Data.Entry.code_page = 0; /* should this be the UNICODE page*/
entry->u.Data.Entry.rsvd = 0;
*info->rva = *info->rva +
ALIGN_VALUE( langinfo->Length, sizeof(uint_32) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -