static RcStatus copyOtherTables( int *err_code ) { uint_32 tablelen; os2_exe_header *oldhead; uint_32 oldoffset; WResFileID oldhandle; RcStatus ret; oldhead = &(Pass2Info.OldFile.u.NEInfo.WinHead); oldoffset = Pass2Info.OldFile.WinHeadOffset; oldhandle = Pass2Info.OldFile.Handle; /* the other tables start at the resident names table and end at the end */ /* of the non-resident names table */ tablelen = (oldhead->nonres_off + oldhead->nonres_size) - ( oldhead->resident_off + oldoffset ); if( RCSEEK( oldhandle, oldhead->resident_off + oldoffset, SEEK_SET ) == -1 ) { *err_code = errno; return( RS_READ_ERROR ); } ret = CopyExeData( Pass2Info.OldFile.Handle, Pass2Info.TmpFile.Handle, tablelen ); *err_code = errno; return( ret ); } /* copyOtherTables */
static void * readString( WResFileID handle, long offset, ReadStrErrInfo *err ) /*****************************************************************************/ { char *retstr; if( RCSEEK( handle, offset, SEEK_SET ) == -1 ) { err->status = RS_READ_ERROR; err->err_code = errno; return( NULL ); } else { retstr = ResReadString( handle, NULL ); if( retstr == NULL ) { if( LastWresStatus() == WRS_READ_INCOMPLETE ) { err->status = RS_READ_INCMPLT; } else { err->status = RS_READ_ERROR; err->err_code = LastWresErr(); } return( NULL ); } else { return( retstr ); } } }
extern uint_32 ComputeSegmentSize( WResFileID handle, SegTable * segs, int shift_count ) { segment_record * currseg; segment_record * afterlast; uint_32 length; WResFileSSize numread; uint_16 num_relocs; length = 0; for( currseg = segs->Segments, afterlast = segs->Segments + segs->NumSegs; currseg < afterlast; currseg++ ) { length += currseg->size; if( currseg->info & SEG_RELOC ) { if( RCSEEK( handle, (((long)currseg->address) << (long)shift_count) + currseg->size, SEEK_SET ) == -1 ) return( 0 ); numread = RCREAD( handle, &num_relocs, sizeof(uint_16) ); if( numread != sizeof(uint_16) ) return( 0 ); length += (unsigned_32)num_relocs * (unsigned_32)OS_RELOC_ITEM_SIZE; } } return( length ); } /* ComputeSegmentSize */
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 */
RcStatus SemCopyDataUntilEOF( WResFileOffset offset, WResFileID handle, void *buff, int buffsize, int *err_code ) /****************************************************************/ { bool error; WResFileSSize numread; if( RCSEEK( handle, offset, SEEK_SET ) == -1 ) { *err_code = errno; return( RS_READ_ERROR ); } numread = RCREAD( handle, buff, buffsize ); while( numread != 0 ) { if( RCIOERR( handle, numread ) ) { *err_code = errno; return( RS_READ_ERROR ); } error = ResWrite( buff, numread, CurrResFile.handle ); if( error ) { *err_code = LastWresErr(); return( RS_WRITE_ERROR ); } numread = RCREAD( handle, buff, buffsize ); } return( RS_OK ); }
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 ); }
bool DumpMenu( uint_32 offset, uint_32 length, WResFileID handle ) /****************************************************************/ { bool error; WResFileOffset prevpos; int depth; /* number of menu levels deep */ MenuItem *item; MenuHeader head; length = length; prevpos = RCSEEK( handle, offset, SEEK_SET ); error = (prevpos == -1); if( !error ) { error = ResReadMenuHeader( &head, handle ); } if( !error ) { PrintHeader( &head ); } depth = 1; while( depth > 0 && !error ) { item = ResNewMenuItem(); error = ResReadMenuItem( item, handle ); if( !error ) { if( item->IsPopup ) { depth++; PrintPopupItem( &(item->Item.Popup) ); if (item->Item.Popup.ItemFlags & MENU_ENDMENU) { depth--; } } else { PrintNormalItem( &(item->Item.Normal) ); if (item->Item.Normal.ItemFlags & MENU_ENDMENU) { depth--; } } } ResFreeMenuItem( item ); } RCSEEK( handle, prevpos, SEEK_SET ); return( error ); }
/* 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 */
/* * readSegTable * NB when an error occurs this function must return without altering errno */ static RcStatus readSegTable( WResFileID handle, uint_32 offset, SegTable * seg ) { int tablesize; WResFileSSize numread; tablesize = seg->NumSegs * sizeof(segment_record); if( RCSEEK( handle, offset, SEEK_SET ) == -1 ) return( RS_READ_ERROR ); numread = RCREAD( handle, seg->Segments, tablesize ); if( numread != tablesize ) { return( RCIOERR( handle, numread ) ? RS_READ_ERROR : RS_READ_INCMPLT ); } return( RS_OK ); } /* readSegTable */
/* * CopyData - */ RcStatus CopyData( uint_32 offset, uint_32 length, WResFileID handle, void *buff, int buffsize, int *err_code ) /***************************************************************************/ { bool error; WResFileSSize numread; if( RCSEEK( handle, offset, SEEK_SET ) == -1 ) { *err_code = errno; return( RS_READ_ERROR ); } while( length > buffsize ) { numread = RCREAD( handle, buff, buffsize ); if( numread != buffsize ) { *err_code = errno; return( RCIOERR( handle, numread ) ? RS_READ_ERROR : RS_READ_INCMPLT ); } length -= buffsize; error = ResWrite( buff, buffsize, CurrResFile.handle ); if( error ) { *err_code = LastWresErr(); return( RS_WRITE_ERROR ); } } numread = RCREAD( handle, buff, length ); if( numread != length ) { *err_code = errno; return( RCIOERR( handle, numread ) ? RS_READ_ERROR : RS_READ_INCMPLT ); } error = ResWrite( buff, length, CurrResFile.handle ); if( error ) { *err_code = errno; return( RS_WRITE_ERROR ); } return( RS_OK ); } /* CopyData */
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 ); }
bool DumpString( uint_32 offset, uint_32 length, WResFileID handle ) /******************************************************************/ { WResFileOffset prevpos; unsigned len; unsigned numread; unsigned cursor; unsigned stringlen; char *stringbuff; prevpos = RCSEEK( handle, offset, SEEK_SET ); if( prevpos == -1 ) return( true ); len = DMP_STR_BUF_LEN; stringbuff = (char *)RCALLOC( len ); if( stringbuff == NULL ) return( true ); printf( "\t\t Strings:\n" ); printf( "\t\t --------" ); numread = 0; stringlen = 0; cursor = 0; do { if( numread == 0 ) { if( length > len ) { length -= len; } else { len = length; length = 0; } numread = RCREAD( handle, stringbuff, len ); cursor = 0; } if( stringlen == 0 ) { stringlen = (unsigned char)stringbuff[cursor++]; if( stringlen != 0 ) { printf( "\n\t\t " ); } ++stringlen; // trailing '\0' } if( cursor < numread ) { for( ; stringlen > 0; --stringlen ) { if( cursor >= numread ) break; if( stringbuff[cursor] != '\0' && stringbuff[cursor] != '\n' ) { putchar( stringbuff[cursor] ); } cursor++; } } else { numread = 0; } } while( length != 0 || numread > 0 ); putchar( '\n' ); RCFREE( stringbuff ); RCSEEK( handle, prevpos, SEEK_SET ); return( false ); }
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; }