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

📄 exerespe.c

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