static RcStatus copyFont( FontInfo * info, WResFileID handle, WResID * name, ResMemFlags flags, int *err_code ) /************************************************************************/ { RcStatus ret; char * buffer; ResLocation loc; long pos; buffer = RCALLOC( FONT_BUFFER_SIZE ); loc.start = SemStartResource(); if( ResWriteFontInfo( info, CurrResFile.handle ) ) { ret = RS_WRITE_ERROR; *err_code = LastWresErr(); } else { pos = RCTELL( handle ); if( pos == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } else { ret = SemCopyDataUntilEOF( pos, handle, buffer, FONT_BUFFER_SIZE, err_code ); } } loc.len = SemEndResource( loc.start ); /* add the font to the RES file directory */ SemAddResourceFree( name, WResIDFromNum( (long)RT_FONT ), flags, loc ); RCFREE( buffer ); return( ret ); } /* copyFont */
static RcStatus copyBitmap( BitmapFileHeader *head, WResFileID handle, WResID *name, ResMemFlags flags, int *err_code ) /**************************************************************************/ { RcStatus ret; char * buffer; ResLocation loc; WResFileOffset pos; buffer = RCALLOC( BITMAP_BUFFER_SIZE ); loc.start = SemStartResource(); pos = RCTELL( handle ); if( pos == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } else { ret = CopyData( pos, head->Size - sizeof(BitmapFileHeader), handle, buffer, BITMAP_BUFFER_SIZE, err_code ); } loc.len = SemEndResource( loc.start ); /* add the bitmap to the RES file directory */ SemAddResourceFree( name, WResIDFromNum( (long)(pointer_int)RT_BITMAP ), flags, loc ); RCFREE( buffer ); return( ret ); } /* copyBitmap */
static RcStatus seekPastResTable( int *err_code ) { long winheadoffset; long seekamount; ExeFileInfo *tmpexe; uint_16 res_tbl_size; tmpexe = &(Pass2Info.TmpFile); if( Pass2Info.OldFile.u.NEInfo.WinHead.target == TARGET_OS2 ) res_tbl_size = tmpexe->u.NEInfo.OS2Res.table_size; else res_tbl_size = tmpexe->u.NEInfo.Res.Dir.TableSize; seekamount = sizeof( os2_exe_header ) + tmpexe->u.NEInfo.Seg.NumSegs * sizeof( segment_record ) + res_tbl_size + tmpexe->u.NEInfo.Res.Str.StringBlockSize; if( RCSEEK( tmpexe->Handle, seekamount, SEEK_CUR ) == -1 ) { *err_code = errno; return( RS_READ_ERROR ); } winheadoffset = RCTELL( tmpexe->Handle ); tmpexe->WinHeadOffset = winheadoffset; return( RS_OK ); } /* seekPastResTable */
static RcStatus copyOneResource( ResTable *restab, FullTypeRecord *type, WResLangInfo *lang, WResResInfo *res, WResFileID reshandle, WResFileID outhandle, int shift_count, int *err_code ) /**********************************************************************/ { RcStatus ret; long out_offset; long align_amount; /* align the output file to a boundary for shift_count */ ret = RS_OK; align_amount = 0; // shut up gcc out_offset = RCTELL( outhandle ); if( out_offset == -1 ) { ret = RS_WRITE_ERROR; *err_code = errno; } if( ret == RS_OK ) { align_amount = AlignAmount( out_offset, shift_count ); if( RCSEEK( outhandle, align_amount, SEEK_CUR ) == -1 ) { ret = RS_WRITE_ERROR; *err_code = errno; } out_offset += align_amount; } if( ret == RS_OK ) { if( RCSEEK( reshandle, lang->Offset, SEEK_SET ) == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } } if( ret == RS_OK ) { ret = CopyExeData( reshandle, outhandle, lang->Length ); *err_code = errno; } if( ret == RS_OK ) { align_amount = AlignAmount( RCTELL( outhandle ), shift_count ); ret = PadExeData( outhandle, align_amount ); *err_code = errno; } if( ret == RS_OK ) { addExeResRecord( restab, type, &(res->ResName), lang->MemoryFlags, out_offset >> shift_count, (lang->Length + align_amount) >> shift_count ); }
ResLocation SemCopyRawFile( const char *filename ) /************************************************/ { WResFileID handle; RcStatus ret; char *buffer; char full_filename[_MAX_PATH]; ResLocation loc; int err_code; WResFileOffset pos; buffer = RCALLOC( BUFFER_SIZE ); if( RcFindResource( filename, full_filename ) == -1 ) { RcError( ERR_CANT_FIND_FILE, filename ); goto HANDLE_ERROR; } if( AddDependency( full_filename ) ) goto HANDLE_ERROR; handle = RcIoOpenInput( full_filename, O_RDONLY | O_BINARY ); if( handle == NIL_HANDLE ) { RcError( ERR_CANT_OPEN_FILE, filename, strerror( errno ) ); goto HANDLE_ERROR; } loc.start = SemStartResource(); pos = RCTELL( handle ); if( pos == -1 ) { RcError( ERR_READING_DATA, full_filename, strerror( errno ) ); RCCLOSE( handle ); goto HANDLE_ERROR; } else { ret = SemCopyDataUntilEOF( pos, handle, buffer, BUFFER_SIZE, &err_code ); if( ret != RS_OK ) { ReportCopyError( ret, ERR_READING_DATA, full_filename, err_code ); RCCLOSE( handle ); goto HANDLE_ERROR; } } loc.len = SemEndResource( loc.start ); RCCLOSE( handle ); RCFREE( buffer ); return( loc ); HANDLE_ERROR: ErrorHasOccured = true; loc.start = 0; loc.len = 0; RCFREE( buffer ); return( loc ); }
/* 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, WResFileID reshandle, WResFileID outhandle, int shift_count, int *err_code ) /************************************************************************/ { RcStatus ret; long out_offset; long align_amount; /* align the output file to a boundary for shift_count */ ret = RS_OK; out_offset = RCTELL( outhandle ); if( out_offset == -1 ) { ret = RS_WRITE_ERROR; *err_code = errno; } if( ret == RS_OK ) { align_amount = AlignAmount( out_offset, shift_count ); if( RCSEEK( outhandle, align_amount, SEEK_CUR ) == -1 ) { ret = RS_WRITE_ERROR; *err_code = errno; } out_offset += align_amount; } if( ret == RS_OK ) { if( RCSEEK( reshandle, lang->Offset, SEEK_SET ) == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } } if( ret == RS_OK ) { ret = CopyExeData( reshandle, outhandle, lang->Length ); *err_code = errno; } if( ret == RS_OK ) { align_amount = AlignAmount( RCTELL( outhandle ), shift_count ); ret = PadExeData( outhandle, align_amount ); *err_code = errno; } return( ret ); } /* copyOneResource */
static RcStatus copyOneCursor( const CurFileDirEntry *entry, WResFileID handle, void *buffer, int buffer_size, BitmapInfoHeader *dibhead, int *err_code ) /*****************************************************************************/ /* NOTE: this routine fills in dibhead as it copies the data */ { RcStatus ret; WResFileOffset curpos; ret = RS_OK; if( RCSEEK( handle, entry->Offset, SEEK_SET ) == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } if( ret == RS_OK ) { ret = ReadBitmapInfoHeader( dibhead, handle ); *err_code = errno; } if( ret == RS_OK ) { if( ResWriteBitmapInfoHeader( dibhead, CurrResFile.handle ) ) { ret = RS_WRITE_ERROR; *err_code = LastWresErr(); } } if( ret == RS_OK ) { curpos = RCTELL( handle ); if( curpos == -1 ) { ret = RS_READ_ERROR; *err_code = errno; } else { ret = CopyData( curpos, entry->Length - sizeof(BitmapInfoHeader), handle, buffer, buffer_size, err_code ); } } return( ret ); }
static bool copyWINBody( void ) { NEExeInfo * tmp; uint_16 sect2mask = 0; uint_16 sect2bits = 0; uint_16 shift_count; long gangloadstart; long gangloadlen; CpSegRc copy_segs_ret; bool use_gangload = false; tmp = &Pass2Info.TmpFile.u.NEInfo; switch( CmdLineParms.SegmentSorting ) { case SEG_SORT_NONE: /* all segments in section 2 */ sect2mask = 0; sect2bits = 0; use_gangload = false; Pass2Info.TmpFile.u.NEInfo.WinHead.align = Pass2Info.OldFile.u.NEInfo.WinHead.align; tmp->Res.Dir.ResShiftCount = computeShiftCount(); break; case SEG_SORT_PRELOAD_ONLY: /* all load on call segments in section 2 */ sect2mask = SEG_PRELOAD; sect2bits = 0; use_gangload = true; checkShiftCount(); break; case SEG_SORT_MANY: /* only load on call, discardable, code segments */ /* in section 2 */ sect2mask = SEG_DATA | SEG_PRELOAD | SEG_DISCARD; sect2bits = SEG_DISCARD; /* set the entry segment to be preload */ { segment_record * seg; /* these two are here because a */ uint_16 entry_seg; /* 71 character field reference */ /* is hard to read */ seg = Pass2Info.OldFile.u.NEInfo.Seg.Segments; entry_seg = Pass2Info.OldFile.u.NEInfo.WinHead.entrynum; seg[entry_seg].info |= SEG_PRELOAD; } use_gangload = true; checkShiftCount(); break; default: break; } /* third arg to Copy???? is false --> copy section one */ gangloadstart = RCTELL( Pass2Info.TmpFile.Handle ); gangloadstart += AlignAmount( gangloadstart, tmp->Res.Dir.ResShiftCount ); copy_segs_ret = CopyWINSegments( sect2mask, sect2bits, false ); switch( copy_segs_ret ) { case CPSEG_SEG_TOO_BIG: if( use_gangload ) { RcWarning( ERR_NO_GANGLOAD ); use_gangload = false; } break; case CPSEG_ERROR: return( true ); case CPSEG_OK: default: break; } if( ! CmdLineParms.NoResFile ) { if( CopyWINResources( sect2mask, sect2bits, false ) != RS_OK ) { return( true ); } } gangloadlen = RCTELL( Pass2Info.TmpFile.Handle ) - gangloadstart; /* third arg to Copy???? is true --> copy section two */ copy_segs_ret = CopyWINSegments( sect2mask, sect2bits, true ); if( copy_segs_ret == CPSEG_ERROR ) { return( true ); } if( !CmdLineParms.NoResFile ) { if( CopyWINResources( sect2mask, sect2bits, true ) != RS_OK ) { return( true ); } } if( use_gangload ) { shift_count = tmp->WinHead.align; tmp->WinHead.gangstart = gangloadstart >> shift_count; tmp->WinHead.ganglength = gangloadlen >> shift_count; tmp->WinHead.otherflags |= WIN_GANGLOAD_PRESENT; } else {
static CpSegRc copyOneSegment( const segment_record * inseg, segment_record * outseg, ExeFileInfo *inexe, ExeFileInfo *outexe, int old_shift_count, int new_shift_count, bool pad_end ) { CpSegRc ret; bool error; WResFileSSize numread; uint_16 numrelocs; long out_offset; long align_amount; uint_32 seg_len = 0L; char zero; zero = 0; error = false; ret = CPSEG_OK; /* check if this is a segment that has no image in the exe file */ if( inseg->address != 0 ) { /* align in the out file so that shift_count will be valid */ out_offset = RCTELL( outexe->Handle ); if( out_offset == -1 ) { error = true; RcError( ERR_WRITTING_FILE, outexe->name, strerror( errno ) ); } if( !error ) { align_amount = AlignAmount( out_offset, new_shift_count ); if( RCSEEK( outexe->Handle, align_amount, SEEK_CUR ) == -1 ) { error = true; RcError( ERR_WRITTING_FILE, outexe->name, strerror( errno ) ); } out_offset += align_amount; } /* move in the in file to the start of the segment */ if( !error ) { /* convert the address to a long before shifting it */ if( RCSEEK( inexe->Handle, (long)inseg->address << old_shift_count, SEEK_SET ) == -1 ) { error = true; RcError( ERR_READING_EXE, inexe->name, strerror( errno ) ); } } if( !error ) { if( inseg->size == 0 ) { seg_len = 0x10000L; } else { seg_len = inseg->size; } error = myCopyExeData( inexe, outexe, seg_len ); } if( (inseg->info & SEG_RELOC) && !error ) { /* read the number of relocation items */ numread = RCREAD( inexe->Handle, &numrelocs, sizeof(uint_16) ); if( numread != sizeof( uint_16 ) ) { error = true; if( RCIOERR( inexe->Handle, numread ) ) { RcError( ERR_READING_EXE, inexe->name, strerror( errno ) ); } else { RcError( ERR_UNEXPECTED_EOF, inexe->name ); } } else { if( RCWRITE( outexe->Handle, &numrelocs, sizeof(uint_16) ) != sizeof( uint_16 ) ) { error = true; RcError( ERR_WRITTING_FILE, outexe->name, strerror( errno ) ); } } /* copy the relocation information */ if( !error ) { error = myCopyExeData( inexe, outexe, numrelocs * OS_RELOC_ITEM_SIZE ); } if( numrelocs * OS_RELOC_ITEM_SIZE + seg_len > 0x10000L ) { ret = CPSEG_SEG_TOO_BIG; } } if( pad_end && ret != CPSEG_SEG_TOO_BIG && !error ) { align_amount = AlignAmount( RCTELL( outexe->Handle ), new_shift_count ); /* make sure there is room for the memory arena header */ if( align_amount < 16 ) { align_amount += 16; } if( RCSEEK( outexe->Handle, align_amount - 1, SEEK_CUR ) == -1 ) { error = true; RcError( ERR_WRITTING_FILE, outexe->name ); } else { /* write something out so if we have just seeked past the * end of the file the file's size will be adjusted * appropriately */ if( RCWRITE( outexe->Handle, &zero, 1 ) != 1 ) { error = true; RcError( ERR_WRITTING_FILE, outexe->name ); } } } } else { out_offset = 0; } /* copy the segment record to outseg */ if( !error ) { outseg->size = inseg->size; outseg->info = inseg->info; outseg->min = inseg->min; outseg->address = out_offset >> new_shift_count; }
RcStatus CopyOS2Resources( void ) { OS2ResEntry *entry; WResDirWindow wind; OS2ResTable *restab; WResLangInfo *lang; WResFileID tmphandle; WResFileID reshandle; RcStatus ret; int err_code; int shift_count; int currseg; segment_record *tmpseg; uint_32 seg_offset; long 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; ret = RS_OK; err_code = 0; tmpseg += currseg; shift_count = Pass2Info.TmpFile.u.NEInfo.WinHead.align; seg_offset = 0; // shut up gcc /* We may need to add padding before the first resource segment */ align_amount = AlignAmount( RCTELL( tmphandle ), shift_count ); if( align_amount ) { ret = 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 */ ret = copyOneResource( lang, reshandle, tmphandle, shift_count, &err_code ); if( ret != RS_OK ) break; CheckDebugOffset( &(Pass2Info.TmpFile) ); } switch( ret ) { 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( ret ); } /* CopyOS2Resources */