📄 exerespe.c
字号:
/******************************************************************/
{
uint_32 str_offset;
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( WRS_OK );
} /* AdjustNameEntry */
static int ComparePEResIdName( PEResEntry * entry1, PEResEntry * 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 WResStatus SortDirEntry( PEResEntry * entry, void * dummy )
/*********************************************************/
{
int num_entries;
dummy = dummy;
if( entry->IsDirEntry ) {
num_entries = entry->Dir.Head.num_name_entries +
entry->Dir.Head.num_id_entries;
qsort( entry->Dir.Children, num_entries, sizeof(PEResEntry),
ComparePEResIdName );
}
return( WRS_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 */
int BuildPEResDir( PEResDir * res, WResDir dir )
{
WResDirWindow wind;
if( WResIsEmpty( dir ) ) {
res->Root.Head.num_name_entries = 0;
res->Root.Head.num_id_entries = 0;
res->Root.Children = NULL;
res->ResRVA = 0;
res->ResOffset = 0;
res->ResSize = 0;
} else {
StringBlockBuild( &res->String, dir, -1 );
res->DirSize = sizeof(resource_dir_header);
PEResDirEntryInit( &res->Root, WResGetNumTypes( dir ) );
wind = WResFirstResource( dir );
while( !WResIsEmptyWindow( wind ) ) {
if( WResIsFirstResOfType( wind ) ) {
if( AddType( res, WResGetTypeInfo( wind ) ) ) return( -1 );
}
if( WResIsFirstLangOfRes( wind ) ) {
if( AddRes( res, wind ) ) return( -1 );
}
AddLang( res, wind );
wind = WResNextResource( wind, dir );
}
}
CompleteTree( res );
return( WRS_OK );
}
typedef struct CopyResInfo {
int to_handle;
int from_handle;
pe_va curr_rva;
} CopyResInfo;
/*
* copyDataEntry: used by PutPEResources
* NB when an error occurs this function MUST return without altering errno
*/
static WResStatus copyDataEntry( PEResEntry *entry, CopyResInfo *copy_info )
/*********************************************************************/
{
WResLangInfo *res_info;
long seekret;
uint_32 diff;
WResStatus status;
if( !entry->IsDirEntry ) {
res_info = WResGetLangInfo( entry->Data.Wind );
seekret = WRESSEEK( copy_info->from_handle, res_info->Offset, SEEK_SET );
if( seekret == -1 ) return( WRS_SEEK_FAILED );
status = CopyData( copy_info->from_handle, copy_info->to_handle,
res_info->Length );
if( status != WRS_OK ) {
return( status );
}
entry->Data.Entry.data_rva = copy_info->curr_rva;
entry->Data.Entry.size = res_info->Length;
entry->Data.Entry.code_page = 0; /* should this be the UNICODE page*/
entry->Data.Entry.rsvd = 0;
diff = ALIGN_VALUE( res_info->Length, sizeof(uint_32) );
copy_info->curr_rva += diff;
if( diff != res_info->Length ) {
/* add the padding */
if (WritePad(copy_info->to_handle, diff-res_info->Length) != WRS_OK)
{
return WRS_WRITE_FAILED;
}
}
}
return( 0 );
} /* copyDataEntry */
/*
* NB: info->rva and info->offset must be aligned to info->align!
* NB: when an error occurs this function MUST return without altering errno
*/
WResStatus CopyPEResData(pResInOutInfo info, PEResDir *outRes) {
CopyResInfo copy_info;
long seekret;
WResStatus ret;
long rdirSize;
rdirSize = outRes->DirSize + outRes->String.StringBlockSize;
rdirSize = ALIGN_VALUE(rdirSize, sizeof(uint_32));
outRes->ResOffset = info->offset;
outRes->ResRVA = info->rva;
copy_info.from_handle = info->res;
copy_info.to_handle = info->obj;
copy_info.curr_rva = info->rva + rdirSize;
seekret = WRESSEEK( info->obj, info->offset+rdirSize, SEEK_SET );
if( seekret == -1 ) return( WRS_SEEK_FAILED );
ret = traverseTree( outRes, ©_info, copyDataEntry );
if( ret ) return( ret ); // error occured
outRes->ResSize = copy_info.curr_rva - outRes->ResRVA;
return( WRS_OK );
}
/*
* writeDirEntry -
* NB when an error occurs this function MUST return without altering errno
*/
WResStatus writeDirEntry( PEResDirEntry *entry, int handle )
/***************************************************************/
{
int num_wrote;
int child_num;
num_wrote = WRESWRITE( handle, &entry->Head, sizeof(resource_dir_header) );
if( num_wrote != sizeof(resource_dir_header) ) return( WRS_WRITE_FAILED );
for( child_num = 0; child_num < entry->Head.num_name_entries +
entry->Head.num_id_entries; child_num++ ) {
num_wrote = WRESWRITE( handle, entry->Children + child_num,
sizeof(resource_dir_entry) );
if( num_wrote != sizeof(resource_dir_entry) ) return( WRS_WRITE_FAILED );
}
return( WRS_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 = WRESWRITE( handle, &entry->Entry, sizeof(resource_entry) );
if( num_wrote != sizeof(resource_entry) ) return( WRS_WRITE_FAILED );
return( WRS_OK );
} /* writeDataEntry */
/*
* writeEntry-
* NB when an error occurs this function MUST return without altering errno
*/
static WResStatus writeEntry( PEResEntry * entry, int * handle )
{
if( entry->IsDirEntry ) {
return( writeDirEntry( &entry->Dir, *handle ) );
} else {
return( writeDataEntry( &entry->Data, *handle ) );
}
} /* writeEntry */
/*
* writeDirectory
* NB when an error occurs this function MUST return without altering errno
*/
static WResStatus WriteDirectory( PEResDir * dir, int handle )
/********************************************************************/
{
long seekret;
int num_wrote;
WResStatus ret;
seekret = WRESSEEK( handle, dir->ResOffset, SEEK_SET );
if( seekret == -1 ) return( WRS_WRITE_FAILED );
/* write the root entry header */
ret = writeDirEntry( &dir->Root, handle );
if( ret != WRS_OK ) return( ret );
ret = traverseTree( dir, &handle, writeEntry );
if( ret != WRS_OK ) return( ret );
if( dir->String.StringBlock != 0 ) {
num_wrote = WRESWRITE( handle, dir->String.StringBlock,
dir->String.StringBlockSize );
if( num_wrote != dir->String.StringBlockSize ) {
return( WRS_WRITE_FAILED );
}
}
return( WRS_OK );
} /* writeDirectory */
void SetPEResObjRecord(pe_object *res_obj, pe_hdr_table_entry *resTblEntry,
PEResDir *outRes) {
/* fill in the object record for the resource object */
strncpy( res_obj->name, RESOURCE_OBJECT_NAME, PE_OBJ_NAME_LEN );
res_obj->virtual_size = 0;
res_obj->rva = outRes->ResRVA;
res_obj->physical_size = outRes->ResSize;
res_obj->physical_offset = outRes->ResOffset;
res_obj->relocs_rva = 0;
res_obj->linnum_rva = 0;
res_obj->num_relocs = 0;
res_obj->num_linnums = 0;
res_obj->flags = PE_OBJ_INIT_DATA | PE_OBJ_READABLE;
/* set the resource element of the table in the header */
resTblEntry->rva = res_obj->rva;
resTblEntry->size = res_obj->physical_size;
}
static void FreeSubDir( PEResDirEntry * subdir )
{
int num_children;
PEResEntry * last_child;
PEResEntry * curr;
num_children = subdir->Head.num_id_entries + subdir->Head.num_name_entries;
last_child = subdir->Children + num_children;
curr = subdir->Children;
while( curr < last_child ) {
if( curr->IsDirEntry ) {
FreeSubDir( &curr->Dir );
}
curr++;
}
WRESFREE( subdir->Children );
}
void FreePEResDir( PEResDir * dir )
{
FreeSubDir( &dir->Root );
WRESFREE( dir->String.StringBlock );
WRESFREE( dir->String.StringList );
}
WResStatus PutPEResources(pResInOutInfo info) {
WResDir dir = WResInitDir();
PEResDir outRes;
int status;
unsigned long newsize;
int dup_discarded;
if (ALIGN_VALUE(info->rva, info->alignRva) != info->rva ||
ALIGN_VALUE(info->offset, info->alignFile) != info->offset)
{
return WRS_BAD_PARAMETER;
}
status = WResReadDir( info->res, dir, &dup_discarded );
if( status ) {
return(status);
}
if( BuildPEResDir( &outRes, dir) ) {
return(-1);
}
status = CopyPEResData( info, &outRes );
if (status) {
return(status);
}
status = WriteDirectory( &outRes, info->obj );
if (status) {
return(status);
}
newsize = ALIGN_VALUE(outRes.ResSize + info->offset, info->alignFile)
- info->offset;
status = WRESSEEK(info->obj, info->offset + outRes.ResSize, SEEK_SET );
if( status == -1 ) return( WRS_SEEK_FAILED );
status = WritePad(info->obj, newsize - outRes.ResSize);
if (status != WRS_OK) return status;
outRes.ResSize = newsize;
SetPEResObjRecord(info->res_obj, info->resTblEntry, &outRes);
FreePEResDir( &outRes );
WResFreeDir(dir);
return WRS_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -