⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exerespe.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
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, &copy_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, &copy_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 + -