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

📄 exeres2.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
字号:
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  NE resource manipulation routines, OS/2 version.
*
****************************************************************************/


#include <string.h>
#include "watcom.h"
#include "exeos2.h"
#include "wresall.h"
#include "global.h"
#include "errors.h"
#include "rcmem.h"
#include "exeutil.h"
#include "iortns.h"


/* Note: IBM's OS/2 RC accepts string resource IDs/types but quietly
 * replaces all strings with zeros when writing out the resources to
 * NE modules. Strange thing to do, but we'll do the same.
 */


/* Build OS/2 NE style resource table. Each resource gets one entry, and
 * resources > 64K will get an additional entry for each 64K chunk.
 */
static void buildOS2ResTable( OS2ResTable *res_tbl, WResDir dir )
/***************************************************************/
{
    WResDirWindow   wind;
    WResLangInfo    *lang;
    OS2ResEntry     *entry;
    WResTypeInfo    *res_type;
    WResResInfo     *resinfo;
    uint_16         type;
    uint_16         id;
    int_32          length;

    entry = res_tbl->resources;

    /* Walk through the WRes directory */
    wind = WResFirstResource( dir );
    while( !WResIsEmptyWindow( wind ) ) {
        lang = WResGetLangInfo( wind );
        res_type = WResGetTypeInfo( wind );
        resinfo  = WResGetResInfo( wind );

        // RT_DEFAULTICON is not written into the executable, ignore
        if( res_type->TypeName.ID.Num == OS2_RT_DEFAULTICON ) {
            wind = WResNextResource( wind, dir );
            continue;
        }

        if( res_type->TypeName.IsName )
            type = 0;
        else
            type = res_type->TypeName.ID.Num;

        if( resinfo->ResName.IsName )
            id = 0;
        else
            id = resinfo->ResName.ID.Num;

        length = lang->Length;

        /* Fill in resource entries */
        entry->res_type   = type;
        entry->res_id     = id;
        entry->wind       = wind;
        entry->mem_flags  = lang->MemoryFlags;
        entry->seg_length = 0;  /* Zero means 64K */
        entry->first_part = TRUE;

        while( length > 0x10000 ) {
            length -= 0x10000;
            entry++;
            entry->res_type   = type;
            entry->res_id     = id;
            entry->wind       = wind;
            entry->mem_flags  = lang->MemoryFlags;
            entry->seg_length = 0;
            entry->first_part = FALSE;
        }
        entry->seg_length = lang->Length % 0x10000;

        wind = WResNextResource( wind, dir );
        entry++;
    }
}


static int compareOS2ResTypeId( const void * _entry1, const void * _entry2 )
/*************************************************************************/
{
    const LXResEntry *entry1 = _entry1;
    const LXResEntry *entry2 = _entry2;

    if( entry1->resource.type_id == entry2->resource.type_id ) {
        return( entry1->resource.name_id - entry2->resource.name_id );
    } else {
        return( entry1->resource.type_id - entry2->resource.type_id );
    }
} /* compareOS2ResTypeId */


extern RcStatus InitOS2ResTable( int *err_code )
/**********************************************/
{
    OS2ResTable         *res;
    WResDir             dir;

    res = &(Pass2Info.TmpFile.u.NEInfo.OS2Res);
    dir = Pass2Info.ResFiles->Dir;

    if( CmdLineParms.NoResFile ) {
        res->resources    = NULL;
        res->num_res_segs = 0;
        res->table_size   = 0;
    } else {
        res->num_res_segs = ComputeOS2ResSegCount( dir );
        /* One resource type/id record per resource segment, 16-bits each */
        res->table_size   = res->num_res_segs * 2 * sizeof( uint_16 );

        res->resources = RcMemMalloc( res->num_res_segs * sizeof( res->resources[0] ) );
        if( res->resources == NULL ) {
            *err_code = errno;
            return( RS_NO_MEM );
        }
        buildOS2ResTable( res, dir );

        /* OS/2 requires resources to be sorted */
        qsort( res->resources, res->num_res_segs,
                sizeof( res->resources[0] ), compareOS2ResTypeId );

    }
    return( RS_OK );
} /* InitOS2ResTable */


/* Compute the number of resource segments in an OS/2 NE module. Each
 * resource gets its own segment and resources > 64K will be split into
 * as many segments as necessary.
 */
extern uint_32 ComputeOS2ResSegCount( WResDir dir )
/*************************************************/
{
    uint_32         length;
    WResDirWindow   wind;
    WResTypeInfo    *res_type;
    WResLangInfo    *res;
    uint_32         num_res_segs;

    num_res_segs = 0;
    wind = WResFirstResource( dir );
    while( !WResIsEmptyWindow( wind ) ) {
        res = WResGetLangInfo( wind );
        res_type = WResGetTypeInfo( wind );

        // RT_DEFAULTICON is not written into the executable, ignore
        if( res_type->TypeName.ID.Num != OS2_RT_DEFAULTICON ) {
            ++num_res_segs;
            length = res->Length;
            while( length > 0x10000 ) {
                length -= 0x10000;
                ++num_res_segs;
            }
        }
        wind = WResNextResource( wind, dir );
    }
    return( num_res_segs );
} /* ComputeOS2ResSegCount */


/* NB: We copy resources in one go even if they span multiple segments.
 * This is fine because all segments but the last one are 64K big, and
 * hence will be nicely aligned.
 */
static RcStatus copyOneResource( WResLangInfo *lang, int reshandle,
            int outhandle, int shift_count, int *err_code )
/*****************************************************************/
{
    RcStatus            error;
    int                 iorc;
    uint_32             out_offset;
    uint_32             align_amount;

    /* align the output file to a boundary for shift_count */
    error = RS_OK;
    out_offset = RcTell( outhandle );
    if( out_offset == -1 ) {
        error = RS_WRITE_ERROR;
        *err_code = errno;
    }
    if( error == RS_OK ) {
        align_amount = AlignAmount( out_offset, shift_count );
        iorc = RcSeek( outhandle, align_amount, SEEK_CUR );
        if( iorc == -1 ) {
            error = RS_WRITE_ERROR;
            *err_code = errno;
        }
        out_offset += align_amount;
    }

    if( error == RS_OK ) {
        iorc = RcSeek( reshandle, lang->Offset, SEEK_SET );
        if( iorc == -1 ) {
            error = RS_READ_ERROR;
            *err_code = errno;
        }
    }
    if( error == RS_OK ) {
        error = CopyExeData( reshandle, outhandle, lang->Length );
        *err_code = errno;
    }
    if( error == RS_OK ) {
        align_amount = AlignAmount( RcTell( outhandle ), shift_count );
        error = PadExeData( outhandle, align_amount );
        *err_code = errno;
    }

    return( error );
} /* copyOneResource */


extern int CopyOS2Resources( void )
{
    OS2ResEntry         *entry;
    WResDirWindow       wind;
    OS2ResTable         *restab;
    WResLangInfo        *lang;
    int                 tmphandle;
    int                 reshandle;
    RcStatus            error;
    int                 err_code;
    int                 shift_count;
    int                 currseg;
    segment_record      *tmpseg;
    uint_32             seg_offset;
    uint_32             align_amount;
    int                 i;

    restab    = &(Pass2Info.TmpFile.u.NEInfo.OS2Res);
    tmphandle = Pass2Info.TmpFile.Handle;
    reshandle = Pass2Info.ResFiles->Handle;
    tmpseg    = Pass2Info.TmpFile.u.NEInfo.Seg.Segments;
    currseg   = Pass2Info.OldFile.u.NEInfo.Seg.NumSegs
                - Pass2Info.OldFile.u.NEInfo.Seg.NumOS2ResSegs;
    entry     = restab->resources;
    error     = RS_OK;

    tmpseg += currseg;
    shift_count = Pass2Info.TmpFile.u.NEInfo.WinHead.align;

    /* We may need to add padding before the first resource segment */
    align_amount = AlignAmount( RcTell( tmphandle ), shift_count );
    if( align_amount ) {
        error = PadExeData( tmphandle, align_amount );
        err_code = errno;
    }

    /* Walk through the resource entries */
    for( i = 0; i < restab->num_res_segs; i++, entry++, tmpseg++ ) {
        wind = entry->wind;
        lang = WResGetLangInfo( wind );

        if( entry->first_part ) {
            seg_offset = RcTell( tmphandle );
        } else {
            seg_offset += 0x10000;
        }

        /* Fill in segment structure */
        tmpseg->address = seg_offset >> shift_count;
        tmpseg->size    = entry->seg_length;
        tmpseg->min     = entry->seg_length;
        tmpseg->info    = SEG_DATA | SEG_READ_ONLY | SEG_LEVEL_3;
        if( entry->mem_flags & MEMFLAG_MOVEABLE )
            tmpseg->info |= SEG_MOVABLE;
        if( entry->mem_flags & MEMFLAG_PURE )
            tmpseg->info |= SEG_PURE;
        if( entry->mem_flags & MEMFLAG_PRELOAD )
            tmpseg->info |= SEG_PRELOAD;
        if( entry->mem_flags & MEMFLAG_DISCARDABLE )
            tmpseg->info |= SEG_DISCARD;

        /* For non-last segment of a resource, there's nothing to copy */
        if( !entry->first_part )
            continue;

        /* Copy resource data */
        error = copyOneResource( lang, reshandle, tmphandle,
                                shift_count, &err_code );

        if( error != RS_OK )
            break;

        CheckDebugOffset( &(Pass2Info.TmpFile) );
    }

    switch( error ) {
    case RS_WRITE_ERROR:
        RcError( ERR_WRITTING_FILE, Pass2Info.TmpFile.name,
                 strerror( err_code ) );
        break;
    case RS_READ_ERROR:
        RcError( ERR_READING_RES, CmdLineParms.OutResFileName,
                 strerror( err_code ) );
        break;
    case RS_READ_INCMPLT:
        RcError( ERR_UNEXPECTED_EOF, CmdLineParms.OutResFileName );
        break;
    default:
        break;
    }
    return( error );
} /* CopyOS2Resources */


/*
 * WriteOS2ResTable
 * NB when an error occurs this function must return without altering errno
 */
extern RcStatus WriteOS2ResTable( int handle, OS2ResTable *restab, int *err_code )
/********************************************************************************/
{
    int                         num_wrote;
    int                         error;
    uint_16                     res_type;
    uint_16                     res_id;
    int                         i;

    error = RS_OK;
    for( i = 0; i < restab->num_res_segs && error == RS_OK; i++ ) {
        res_type = restab->resources[i].res_type;
        res_id   = restab->resources[i].res_id;

        num_wrote = RcWrite( handle, &res_type, sizeof( uint_16 ) );
        if( num_wrote != sizeof( uint_16 ) ) {
            error = RS_WRITE_ERROR;
        } else {
            num_wrote = RcWrite( handle, &res_id, sizeof( uint_16 ) );
            if( num_wrote != sizeof( uint_16 ) ) {
                error = RS_WRITE_ERROR;
            }
        }
    }

    *err_code = errno;
    if( restab->resources != NULL ) {
        RcMemFree( restab->resources );
    }

    return( error );
} /* WriteOS2ResTable */

⌨️ 快捷键说明

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