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

📄 exerespe.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
    }
    return( RS_OK );
}

/*
 * writeEntry-
 * NB when an error occurs this function MUST return without altering errno
 */
static RcStatus writeEntry( PEResEntry * entry, void * _handle )
/**************************************************************/
{
    int *handle = _handle;

    if( entry->IsDirEntry ) {
        return( writeDirEntry( &entry->u.Dir, *handle ) );
    } else {
        return( writeDataEntry( &entry->u.Data, *handle ) );
    }
} /* writeEntry */

/*
 * writeDirectory
 * NB when an error occurs this function MUST return without altering errno
 */
static RcStatus writeDirectory( PEResDir * dir, int handle )
/********************************************************************/
{
    long        seek_rc;
    int         num_wrote;
    RcStatus    ret;

    seek_rc = RcSeek( handle, dir->ResOffset, SEEK_SET );
    if( seek_rc == -1 ) return( RS_WRITE_ERROR );

    /* write the root entry header */
    ret = writeDirEntry( &dir->Root, handle );
    if( ret != RS_OK ) return( ret );

    ret = traverseTree( dir, &handle, writeEntry );
    if( ret != RS_OK ) return( ret );

    if( dir->String.StringBlock != 0 ) {
        num_wrote = RcWrite( handle, dir->String.StringBlock,
                                dir->String.StringBlockSize );
        if( num_wrote != dir->String.StringBlockSize ) {
            return( RS_WRITE_ERROR );
        }
    }

    return( RS_OK );
} /* writeDirectory */

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->u.Dir );
        }
        curr++;
    }

    RcMemFree( subdir->Children );
}

static void FreePEResDir( PEResDir * dir )
/****************************************/
{
    FreeSubDir( &dir->Root );
    RcMemFree( dir->String.StringBlock );
    RcMemFree( dir->String.StringList );
}

#ifndef INSIDE_WLINK
extern int RcPadFile( int handle, long pad )
/******************************************/
{
    char        zero = 0;

    if( pad > 0 ) {
        if( RcSeek( handle, pad - 1, SEEK_CUR ) == -1 ) {
            return( TRUE );
        }
        if( RcWrite( handle, &zero, 1 ) != 1 )  {
            return( TRUE );
        }
    }
    return( FALSE );
}
#endif

/*
 * padObject
 * NB when an error occurs this function MUST return without altering errno
 */
static int padObject( PEResDir *dir, ExeFileInfo *tmp, long size )
{
    long        pos;
    long        pad;

    pos = RcTell( tmp->Handle );
    if( pos == -1 ) return( TRUE );
    pad = dir->ResOffset + size - pos;
    if( pad > 0 ) {
        RcPadFile( tmp->Handle, pad );
    }
    CheckDebugOffset( tmp );
    return( FALSE );
#if(0)
    long        seek_rc;
    char        zero=0;

    seek_rc = RcSeek( tmp->Handle, dir->ResOffset, SEEK_SET );
    if( seek_rc == -1 ) return( TRUE );
    seek_rc = RcSeek( tmp->Handle, size-1, SEEK_CUR );
    if( seek_rc == -1 ) return( TRUE );
    if( RcWrite( tmp->Handle, &zero, 1 ) != 1 ) return( TRUE );
    CheckDebugOffset( tmp );
    return( FALSE );
#endif
}

static void fillResourceObj( pe_object *res_obj, PEResDir *dir,
                             uint_32 alignment )
/****************************************************************/
{
    strncpy( res_obj->name, RESOURCE_OBJECT_NAME, PE_OBJ_NAME_LEN );
    res_obj->virtual_size = 0;
    res_obj->rva = dir->ResRVA;
    res_obj->physical_size = ALIGN_VALUE( dir->ResSize, alignment );
    res_obj->physical_offset = dir->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;
}

// merge the directories of all the res files into one large directory
// stored on the first resfileinfo node
int mergeDirectory( ResFileInfo *resfiles, WResMergeError **errs )
/******************************************************************/
{
    ResFileInfo         *cur;

    if( errs != NULL ) *errs = NULL;
    if( resfiles == NULL ) return( FALSE );
    cur = resfiles->next;
    while( cur != NULL ) {
        if( WResMergeDirs( resfiles->Dir, cur->Dir, errs ) ) {
            return( TRUE );
        }
        cur = cur->next;
    }
    return( FALSE );
}

static void setDataOffsets( PEResDir *dir, unsigned_32 *curr_rva,
                                ResFileInfo *resfiles, int writebyfile )
/****************************************************************/
{
    DataEntryCookie     cookie;

    cookie.rva = curr_rva;
    if( writebyfile ) {
        while( resfiles != NULL ) {
            cookie.curfile = resfiles;
            traverseTree( dir, &cookie, setDataEntry );
            resfiles = resfiles->next;
        }
    } else {
        cookie.curfile = NULL;
        traverseTree( dir, &cookie, setDataEntry );
    }
}

#define NAME_LEN        256
static void reportDuplicateResources( WResMergeError *errs )
/************************************************************/
{
    WResMergeError  *curerr;
    ResFileInfo     *file1;
    ResFileInfo     *file2;
    WResResInfo     *resinfo;
    WResTypeInfo    *typeinfo;

    curerr = errs;
    while( curerr != NULL ) {
        resinfo = WResGetResInfo( curerr->dstres );
        typeinfo = WResGetTypeInfo( curerr->dstres );
        file1 = WResGetFileInfo( curerr->dstres );
        file2 = WResGetFileInfo( curerr->srcres );
        ReportDupResource( &resinfo->ResName, &typeinfo->TypeName,
                           file1->name, file2->name, FALSE );
        curerr = curerr->next;
    }
}

extern int BuildResourceObject( ExeFileInfo *exeinfo, ResFileInfo *resinfo,
                                pe_object *res_obj, unsigned_32 rva,
                                unsigned_32 offset, int writebyfile )
/**************************************************************************/
{
    PEResDir *      dir;
    RcStatus        status;
    unsigned_32     curr_rva;
    WResMergeError  *errs;
    ResFileInfo     *errres;

    dir = &exeinfo->u.PEInfo.Res;

    mergeDirectory( resinfo, &errs );
    if( errs != NULL ) {
        reportDuplicateResources( errs );
        WResFreeMergeErrors( errs );
        return( TRUE );
    }
    if( PEResDirBuild( dir, resinfo->Dir ) ) {
        RcError( ERR_INTERNAL, INTERR_ERR_BUILDING_RES_DIR );
        return( TRUE );
    }
    CompleteTree( dir );
    exeinfo->u.PEInfo.Res.ResOffset = offset;
    exeinfo->u.PEInfo.Res.ResRVA = rva;
    curr_rva = rva + exeinfo->u.PEInfo.Res.DirSize
               + exeinfo->u.PEInfo.Res.String.StringBlockSize;
    curr_rva = ALIGN_VALUE( curr_rva, sizeof( uint_32 ) );
    setDataOffsets( dir, &curr_rva, resinfo, writebyfile );
    status = writeDirectory( dir, exeinfo->Handle );
    if( status != RS_OK ) {
        RcError( ERR_WRITTING_FILE, exeinfo->name, strerror( errno ) );
        return( TRUE );
    }

    status = copyPEResources( exeinfo, resinfo, exeinfo->Handle,
                              writebyfile, &errres );
    // warning - the file names output in these messages could be
    //          incorrect if the -fr switch is in use
    if( status != RS_OK  ) {
        switch( status ) {
        case RS_WRITE_ERROR:
            RcError( ERR_WRITTING_FILE, exeinfo->name, strerror( errno ) );
            break;
        case RS_READ_ERROR:
            RcError( ERR_READING_RES, errres->name, strerror( errno )  );
            break;
        case RS_OPEN_ERROR:
            RcError( ERR_CANT_OPEN_FILE, errres->name, strerror( errno ) );
        case RS_READ_INCMPLT:
            RcError( ERR_UNEXPECTED_EOF, errres->name );
            break;
        default:
            RcError( ERR_INTERNAL, INTERR_UNKNOWN_RCSTATUS );
            break;
        }
        return( TRUE );
    }

    exeinfo->u.PEInfo.Res.ResSize = curr_rva - rva;
    fillResourceObj( res_obj, dir, exeinfo->u.PEInfo.WinHead->file_align );
    if( padObject( dir, exeinfo, res_obj->physical_size ) ) {
        RcError( ERR_WRITTING_FILE, exeinfo->name, strerror( errno ) );
        return( TRUE );
    }

    /* set the resource element of the table in the header */
    exeinfo->u.PEInfo.WinHead->table[ PE_TBL_RESOURCE ].rva = res_obj->rva;
    exeinfo->u.PEInfo.WinHead->table[ PE_TBL_RESOURCE ].size =
                                        res_obj->physical_size;

    FreePEResDir( dir );

    return( FALSE );
} /* BuildResourceObject */


#ifndef INSIDE_WLINK
int RcBuildResourceObject( void ) {
/***********************************/

    pe_object           *res_obj;
    unsigned_32         rva;
    unsigned_32         offset;
    RcStatus            error;
    ExeFileInfo         *exeinfo;

    exeinfo = &Pass2Info.TmpFile;
    if( CmdLineParms.NoResFile ) {
        exeinfo->u.PEInfo.WinHead->table[ PE_TBL_RESOURCE ].rva = 0;
        exeinfo->u.PEInfo.WinHead->table[ PE_TBL_RESOURCE ].size = 0;
        error = RS_OK;
    } else {
        res_obj = exeinfo->u.PEInfo.Objects
                  + exeinfo->u.PEInfo.WinHead->num_objects - 1;
        rva = GetNextObjRVA( &exeinfo->u.PEInfo );
        offset = GetNextObjPhysOffset( &exeinfo->u.PEInfo );
        error = BuildResourceObject( exeinfo, Pass2Info.ResFiles,
                                     res_obj, rva, offset,
                                     !Pass2Info.AllResFilesOpen );
// use of CmdLineParms.WritableRes has been commented out in param.c
// removed here too as it wasn't initialised anymore (Ernest ter Kuile 31 aug 2003)
//        if( CmdLineParms.WritableRes ) {
//            res_obj->flags |= PE_OBJ_WRITABLE;
//        }
    }

    return( error );
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -