📄 pass2.c
字号:
info |= OS2_PROT_MODE_ONLY;
}
/* copy the fields in the os2_exe_header then change some of them */
tmpfile->WinHeadOffset = oldfile->WinHeadOffset;
/* copy the WinHead fields up to, but excluding, the segment_off field */
memcpy( &(tmpne->WinHead), &(oldne->WinHead),
offsetof(os2_exe_header, segment_off) );
tmpne->WinHead.info = info;
tableshift = tmpne->Res.Dir.TableSize +
tmpne->Res.Str.StringBlockSize -
(oldne->WinHead.resident_off - oldne->WinHead.resource_off );
tmpne->WinHead.entry_off = oldne->WinHead.entry_off + tableshift;
tmpne->WinHead.resident_off = oldne->WinHead.resident_off + tableshift;
tmpne->WinHead.module_off = oldne->WinHead.module_off + tableshift;
tmpne->WinHead.import_off = oldne->WinHead.import_off + tableshift;
tmpne->WinHead.nonres_off = oldne->WinHead.nonres_off + tableshift;
tmpne->WinHead.segment_off = sizeof(os2_exe_header);
tmpne->WinHead.resource_off = tmpne->WinHead.segment_off +
tmpne->Seg.NumSegs * sizeof(segment_record);
tmpne->WinHead.movable = oldne->WinHead.movable;
tmpne->WinHead.resource = tmpne->Res.Dir.NumResources;
tmpne->WinHead.target = oldne->WinHead.target;
/* |= the next one since the WIN_GANGLOAD_PRESENT flag may be set */
tmpne->WinHead.otherflags |= oldne->WinHead.otherflags;
tmpne->WinHead.swaparea = 0; /* What is this field for? */
tmpne->WinHead.expver = CmdLineParms.VersionStamp;
/* seek to the start of the os2_exe_header in tmpfile */
seekrc = RcSeek( tmpfile->Handle, tmpfile->WinHeadOffset, SEEK_SET );
if( seekrc == -1 ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
/* write the header */
numwrote = RcWrite( tmpfile->Handle, &(tmpne->WinHead),
sizeof(os2_exe_header) );
if( numwrote != sizeof(os2_exe_header) ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
/* write the segment table */
if( tmpne->Seg.NumSegs > 0 ) {
numwrote = RcWrite( tmpfile->Handle, tmpne->Seg.Segments,
tmpne->Seg.NumSegs * sizeof(segment_record) );
if( numwrote != tmpne->Seg.NumSegs * sizeof(segment_record) ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
}
/* write the resource table */
error = WriteResTable( tmpfile->Handle, &(tmpne->Res), err_code );
return( error );
} /* writeHeadAndTables */
/*
* Processing OS/2 NE modules is very very similar to Windows NE processing
* but there are enough differences in detail to warrant separate
* implementation to keep the two cleaner.
*/
static int writeOS2HeadAndTables( int *err_code )
{
ExeFileInfo * oldfile;
ExeFileInfo * tmpfile;
NEExeInfo * oldne;
NEExeInfo * tmpne;
uint_16 tableshift; /* amount the tables are shifted in the */
/* tmp file */
long seekrc;
int numwrote;
int error;
oldfile = &(Pass2Info.OldFile);
oldne = &oldfile->u.NEInfo;
tmpfile = &(Pass2Info.TmpFile);
tmpne = &tmpfile->u.NEInfo;
/* copy the fields in the os2_exe_header then change some of them */
tmpfile->WinHeadOffset = oldfile->WinHeadOffset;
/* copy the WinHead fields up to, but excluding, the segment_off field */
memcpy( &(tmpne->WinHead), &(oldne->WinHead),
offsetof(os2_exe_header, segment_off) );
tmpne->WinHead.info = oldne->WinHead.info;
tmpne->WinHead.segment_off = sizeof(os2_exe_header);
tmpne->WinHead.resource_off = tmpne->WinHead.segment_off +
tmpne->Seg.NumSegs * sizeof(segment_record);
tableshift = tmpne->OS2Res.table_size -
(oldne->WinHead.resident_off - oldne->WinHead.resource_off) +
(tmpne->WinHead.resource_off - oldne->WinHead.resource_off);
tmpne->WinHead.entry_off = oldne->WinHead.entry_off + tableshift;
tmpne->WinHead.resident_off = oldne->WinHead.resident_off + tableshift;
tmpne->WinHead.module_off = oldne->WinHead.module_off + tableshift;
tmpne->WinHead.import_off = oldne->WinHead.import_off + tableshift;
tmpne->WinHead.nonres_off = oldne->WinHead.nonres_off + tableshift;
tmpne->WinHead.movable = oldne->WinHead.movable;
tmpne->WinHead.resource = tmpne->OS2Res.num_res_segs;
tmpne->WinHead.target = oldne->WinHead.target;
tmpne->WinHead.otherflags = oldne->WinHead.otherflags;
tmpne->WinHead.segments = tmpne->Seg.NumSegs;
/* seek to the start of the os2_exe_header in tmpfile */
seekrc = RcSeek( tmpfile->Handle, tmpfile->WinHeadOffset, SEEK_SET );
if( seekrc == -1 ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
/* write the header */
numwrote = RcWrite( tmpfile->Handle, &(tmpne->WinHead),
sizeof(os2_exe_header) );
if( numwrote != sizeof(os2_exe_header) ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
/* write the segment table */
if( tmpne->Seg.NumSegs > 0 ) {
numwrote = RcWrite( tmpfile->Handle, tmpne->Seg.Segments,
tmpne->Seg.NumSegs * sizeof(segment_record) );
if( numwrote != tmpne->Seg.NumSegs * sizeof(segment_record) ) {
*err_code = errno;
return( RS_WRITE_ERROR );
}
}
/* write the resource table */
error = WriteOS2ResTable( tmpfile->Handle, &(tmpne->OS2Res), err_code );
return( error );
} /* writeOS2HeadAndTables */
static int findEndOfResources( int *err_code )
/* if this exe already contains resources find the end of them so we don't
copy them with debug information. Otherwise the file will grow whenever
a resource file is added */
{
NEExeInfo *oldneinfo;
uint_32 *debugoffset;
int oldhdl;
int rc;
unsigned i;
uint_32 oldoffset;
uint_16 alignshift;
uint_32 end;
uint_32 tmp;
resource_type_record typeinfo;
resource_record nameinfo;
end = 0;
oldoffset = Pass2Info.OldFile.WinHeadOffset;
oldneinfo = &Pass2Info.OldFile.u.NEInfo;
oldhdl = Pass2Info.OldFile.Handle;
debugoffset = &Pass2Info.OldFile.DebugOffset;
if( oldneinfo->WinHead.resource_off == oldneinfo->WinHead.resident_off ) {
return( RS_OK );
}
rc = RcSeek( oldhdl, oldneinfo->WinHead.resource_off + oldoffset,
SEEK_SET );
if( rc == -1 ) {
*err_code = errno;
return( RS_READ_ERROR );
}
rc = RcRead( oldhdl, &alignshift, sizeof( uint_16 ) );
if( rc != sizeof( uint_16 ) ) {
*err_code = errno;
if( rc == -1 ) {
return( RS_READ_ERROR );
} else {
return( RS_READ_INCMPLT );
}
}
alignshift = 1 << alignshift;
rc = RcRead( oldhdl, &typeinfo, sizeof( resource_type_record ) );
if( rc != sizeof( resource_type_record ) ) {
*err_code = errno;
if( rc == -1 ) {
return( RS_READ_ERROR );
} else {
return( RS_READ_INCMPLT );
}
}
while( typeinfo.type != 0 ) {
for( i=0; i < typeinfo.num_resources; i++ ) {
rc = RcRead( oldhdl, &nameinfo, sizeof( resource_record ) );
if( rc != sizeof( resource_record ) ) {
*err_code = errno;
if( rc == -1 ) {
return( RS_READ_ERROR );
} else {
return( RS_READ_INCMPLT );
}
}
tmp = nameinfo.offset + nameinfo.length;
if( tmp > end ) end = tmp;
}
rc = RcRead( oldhdl, &typeinfo, sizeof( resource_type_record ) );
if( rc != sizeof( resource_type_record ) ) {
*err_code = errno;
if( rc == -1 ) {
return( RS_READ_ERROR );
} else {
return( RS_READ_INCMPLT );
}
}
}
end *= alignshift;
if( end > *debugoffset ) {
*debugoffset = end;
}
return( RS_OK );
}
/*
* writePEHeadAndObjTable
* NB when an error occurs this function must return without altering errno
*/
static RcStatus writePEHeadAndObjTable( void )
{
ExeFileInfo * tmp;
PEExeInfo * pe_info;
pe_object * last_object;
long seek_rc;
int num_wrote;
int obj_num;
uint_32 image_size;
tmp = &Pass2Info.TmpFile;
pe_info = &tmp->u.PEInfo;
/* adjust the image size in the header */
last_object = &pe_info->Objects[ pe_info->WinHead->num_objects - 1 ];
image_size = last_object->rva + last_object->physical_size;
image_size = ALIGN_VALUE( image_size, pe_info->WinHead->object_align );
pe_info->WinHead->image_size = image_size;
seek_rc = RcSeek( tmp->Handle, tmp->WinHeadOffset, SEEK_SET );
if( seek_rc == -1 ) return( RS_WRITE_ERROR );
num_wrote = RcWrite( tmp->Handle, pe_info->WinHead, sizeof(pe_header) );
if( num_wrote != sizeof(pe_header) ) return( RS_WRITE_ERROR );
for( obj_num = 0; obj_num < pe_info->WinHead->num_objects; obj_num++ ) {
num_wrote = RcWrite( tmp->Handle, pe_info->Objects + obj_num,
sizeof(pe_object) );
if( num_wrote != sizeof(pe_object) ) return( RS_WRITE_ERROR );
}
return( RS_OK );
} /* writePEHeadAndObjTable */
/*
* Windows NE files store resources in a special data structure. OS/2 NE
* modules are quite different and store each resource in its own data
* segment(s). The OS/2 resource table is completely different as well and
* only contains resource types/IDs.
*/
extern int MergeResExeNE( void )
{
RcStatus error;
int err_code;
error = copyStubFile( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
error = AllocAndReadSegTables( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
InitResTable();
error = seekPastResTable( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
error = findEndOfResources( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
error = copyOtherTables( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
error = copyBody();
if( error ) return( FALSE );
if( StopInvoked ) goto STOP_ERROR;
error = copyDebugInfo();
if( error != RS_OK ) {
err_code = errno;
goto HANDLE_ERROR;
}
if( StopInvoked ) goto STOP_ERROR;
error = writeHeadAndTables( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
return( TRUE );
HANDLE_ERROR:
switch( error ) {
case RS_READ_ERROR:
RcError( ERR_READING_EXE, Pass2Info.OldFile.name,
strerror( err_code ) );
break;
case RS_READ_INCMPLT:
RcError( ERR_UNEXPECTED_EOF, Pass2Info.OldFile.name );
break;
case RS_WRITE_ERROR:
RcError( ERR_WRITTING_TMP, Pass2Info.TmpFile.name,
strerror( err_code ) );
break;
case RS_NO_MEM:
break;
default:
RcError( ERR_INTERNAL, INTERR_UNKNOWN_RCSTATUS );
}
return( FALSE );
STOP_ERROR:
RcFatalError( ERR_STOP_REQUESTED );
#if !defined( __WATCOMC__ )
return( FALSE );
#endif
} /* MergeResExeNE */
extern int MergeResExeOS2NE( void )
{
RcStatus error;
int err_code;
error = copyStubFile( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
error = InitOS2ResTable( &err_code );
if( error != RS_OK ) goto HANDLE_ERROR;
if( StopInvoked ) goto STOP_ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -