wbind.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 476 行
C
476 行
/****************************************************************************
*
* 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: WBIND for the Win386 extender.
*
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <process.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "banner.h"
#define FAR _far
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef WORD HINSTANCE;
typedef char FAR *LPSTR;
#include "winext.h"
#include "watcom.h"
#include "exedos.h"
#include "exeos2.h"
#undef _WBIND_VERSION_
#define _WBIND_VERSION_ "2.3"
#define IO_BUFF 64000
#define TRUE 1
#define FALSE 0
#define MAGIC_OFFSET 0x38L
#define MAX_DESC 80
#define RC_STR "wrc"
static int quietFlag=FALSE;
static void updateNHStuff( int handle, char *modname, char *desc )
{
dos_exe_header dh;
os2_exe_header nh;
long off;
int len;
lseek( handle, 0, SEEK_SET );
read( handle, &dh, sizeof( dh ) );
off = (dh.file_size-1)*512L + dh.mod_size;
lseek( handle, off, SEEK_SET );
read( handle, &nh, sizeof( nh ) );
off += nh.resident_off+1L;
lseek( handle, off, SEEK_SET );
write( handle, modname, 8 );
if( desc == NULL ) {
desc = modname;
len = 8;
} else {
len = strlen( desc );
if( len > MAX_DESC ) {
len = MAX_DESC;
}
}
off = nh.nonres_off+1L;
lseek( handle, off, SEEK_SET );
write( handle, desc, len );
}
static void myPrintf( char *str, ... )
{
va_list al;
if( !quietFlag ) {
va_start( al, str );
vprintf( str, al );
va_end( al );
}
} /* myPrintf */
static void doError( char *str, ... )
{
va_list al;
va_start( al, str );
vprintf( str, al );
va_end( al );
printf("\n");
exit( 1 );
} /* doError */
static void doBanner( void )
{
myPrintf( "%s\n", banner1w( "Win386 Bind Utility",_WBIND_VERSION_ ) );
myPrintf( "%s\n", banner2( "1991" ) );
myPrintf( "%s\n", banner3 );
myPrintf( "%s\n", banner3a );
myPrintf("\n");
}
static void doUsage( char *str )
{
quietFlag = FALSE;
doBanner();
if( str != NULL ) {
printf("Error - %s\n\n", str );
}
printf("Usage: wbind [file] [-udnq] [-D \"<desc>\"] [-s <supervisor>] [-R <rc options>]\n" );
printf(" [file] is the name of the 32-bit windows exe to bind\n" );
printf(" -u : unbind a bound executable\n" );
printf(" -d : build a 32-bit dll\n" );
printf(" -n : no resource compile required\n" );
printf(" -q : quiet mode\n" );
printf(" -D \"<desc>\" : specify the description field\n" );
printf(" -s <supervisor> : specifies the path/name of the windows supervisor\n" );
printf(" -R <rc options> : all options after -R are passed to the resource\n" );
printf(" compiler. Note that ONLY the options after -R are\n" );
printf(" given to the resource compiler.\n" );
exit( 0 );
} /* doUsage */
static void *myAlloc( size_t amount )
{
void *tmp;
tmp = malloc( amount );
if( tmp == NULL ) {
doError("Out of memory!");
}
return( tmp );
}
static void errPrintf( char *str, ... )
{
va_list al;
va_start( al, str );
vfprintf( stderr, str, al );
va_end( al );
} /* errPrintf */
static long CopyFile( int in, int out, char *infile, char *outfile )
{
unsigned size;
unsigned len;
unsigned bufsize;
long totalsize;
void *buff;
buff = myAlloc( IO_BUFF );
bufsize = IO_BUFF;
totalsize = 0L;
for( ;; ) {
size = read( in, buff, bufsize );
if( size == 0 ) {
break;
}
if( size == -1 ) {
doError( "Error reading file \"%s\"", infile );
}
len = write( out, buff, size );
if( len != size ) {
doError( "Error writing file \"%s\"", outfile );
}
totalsize += len;
if( (unsigned) size != bufsize ) {
break;
}
}
free( buff );
return( totalsize );
}
void FindExtender( char *extname, char *winext )
{
char *watcom;
_searchenv( extname, "PATH", winext );
if( winext[0] == '\0' ) {
watcom = getenv( "WATCOM" );
if( watcom != NULL ) {
strcpy( winext, watcom );
strcat( winext, "\\binw\\" );
strcat( winext, extname );
if( access( winext, R_OK ) == -1 ) {
winext[0] = '\0'; // indicate file not found
}
}
if( winext[0] == '\0' ) {
doError( "Could not find \"%s\" in your path", extname );
}
}
}
int main( int argc, char *argv[] )
{
int in,out,i,rcparm=0,pcnt;
int Rflag=FALSE,nflag=FALSE;
int uflag=FALSE;
int dllflag=FALSE;
char *wext=NULL;
long tsize=0;
char drive[_MAX_DRIVE],dir[_MAX_DIR],fname[_MAX_FNAME];
char ext[_MAX_EXT];
char rex[_MAX_PATH];
char exe[_MAX_PATH];
char dll[_MAX_PATH];
char res[_MAX_PATH];
char winext[_MAX_PATH];
char rc[256];
long totalsize;
const char **arglist;
char *path = NULL;
int currarg,len;
rex_exe re;
long exelen;
char *desc=NULL;
/*
* get parms
*/
if( argc < 2 ) {
doUsage( NULL );
}
currarg=1;
while( currarg < argc ) {
#ifdef __UNIX__
if( argv[ currarg ][0] == '-' ) {
#else
if( argv[ currarg ][0] == '/' || argv[ currarg ][0] == '-' ) {
#endif
len = strlen( argv[ currarg ] );
for( i=1; i<len; i++ ) {
switch( argv[ currarg ][i] ) {
case '?': doUsage( NULL );
case 'D':
currarg++;
desc = argv[ currarg ];
break;
case 's':
currarg++;
wext = argv[ currarg ];
break;
case 'q':
quietFlag = TRUE;
break;
case 'u':
uflag = TRUE;
break;
case 'n':
nflag = TRUE;
break;
case 'd':
dllflag = TRUE;
break;
case 'R': case 'r':
Rflag=TRUE;
rcparm = currarg+1;
if( rcparm == argc ) {
doUsage("must specify resource compiler command line" );
}
break;
}
}
if( Rflag ) {
break;
}
} else {
if( path != NULL ) {
doUsage( "Only one executable may be specified" );
}
path = argv[ currarg ];
}
currarg++;
}
if( path == NULL ) {
doUsage( "No executable to bind" );
}
doBanner();
/*
* get files to use
*/
_splitpath( path, drive, dir, fname, ext );
_makepath( rex, drive, dir, fname, ".rex" );
if( dllflag ) {
_makepath( dll, drive, dir, fname, ".dll" );
}
_makepath( exe, drive, dir, fname, ".exe" );
_makepath( res, drive, dir, fname, "" );
/*
* do the unbind
*/
if( uflag ) {
if( ext[0] == 0 ) {
path = exe;
}
in = open( path, O_RDONLY | O_BINARY );
if( in < 0 ) {
doError( "Could not open %s", path );
}
out = open( rex, O_CREAT | O_TRUNC|O_WRONLY | O_BINARY, S_IRWXU );
if( out < 0 ) {
doError( "Could not open %s", rex );
}
lseek( in, MAGIC_OFFSET, SEEK_SET );
read( in, &exelen, sizeof( DWORD ) );
lseek( in, exelen, SEEK_SET );
read( in, &re, sizeof( rex_exe ) );
if( !(re.sig[0] == 'M' && re.sig[1] == 'Q') ) {
doError( "Not a bound Open Watcom 32-bit Windows application" );
}
lseek( in, exelen, SEEK_SET );
CopyFile( in, out, path, rex );
close( in );
close( out );
myPrintf( ".rex file %s created", rex );
exit( 0 );
}
if( wext == NULL ) {
if( dllflag ) {
FindExtender( "w386dll.ext", winext );
} else {
FindExtender( "win386.ext", winext );
}
} else {
strcpy( winext, wext );
}
if( dllflag ) {
myPrintf("Loading 32-bit Windows DLL Supervisor \"%s\"\n",winext );
} else {
myPrintf("Loading 32-bit Windows Supervisor \"%s\"\n",winext );
}
/*
* open files
*/
in = open( winext, O_RDONLY | O_BINARY );
if( in < 0 ) {
doError( "Could not open %s", winext );
}
out = open( exe, O_CREAT | O_TRUNC|O_WRONLY | O_BINARY, S_IRWXU );
if( out < 0 ) {
doError( "Could not open %s", exe );
}
/*
* copy extender over
*/
CopyFile( in, out, winext, exe );
close( in );
close( out );
/*
* run the resource compiler
*/
if( !nflag ) {
myPrintf("Invoking the resource compiler...\n");
if( Rflag ) {
strcpy( rc, RC_STR );
arglist = myAlloc( sizeof(char *) *(argc-rcparm +3) );
pcnt = 1;
for( i=rcparm;i<argc;i++ ) {
arglist[pcnt++] = argv[i];
strcat( rc," " );
strcat( rc, argv[i] );
}
} else {
sprintf( rc, RC_STR " %s", res );
arglist = myAlloc( sizeof(char *) * 3 );
arglist[1] = res;
pcnt = 2;
}
arglist[0] = RC_STR;
arglist[pcnt] = NULL;
myPrintf( "%s\n",rc );
i = spawnvp( P_WAIT, RC_STR, arglist );
if( i == -1 ) {
remove( exe );
switch( errno ) {
case E2BIG:
doError( "Argument list too big. Resource compiler step failed." );
break;
case ENOENT:
doError( "Could not find wrc.exe." );
break;
case ENOMEM:
doError( "Not enough memory. Resource compiler step failed." );
break;
}
doError( "Unknown error %d, resource compiler step failed.", errno );
}
if( i != 0 ) {
remove( exe );
errPrintf( "Resource compiler failed, return code = %d\n", i );
exit( i );
}
}
/*
* copy the rex file onto the end
*/
in = open( rex, O_RDONLY | O_BINARY );
if( in < 0 ) {
doError( "Could not open %s", rex );
}
out = open( exe, O_RDWR | O_BINARY );
if( out < 0 ) {
doError( "Could not open %s", exe );
}
lseek( out, 0, SEEK_END );
tsize = tell( out );
totalsize = CopyFile( in, out, rex, exe );
close( in );
/*
* noodle the file: change name, and then
* write the file size into the old exe header (for
* use by the loader)
*/
lseek( out, MAGIC_OFFSET, SEEK_SET );
write( out, &tsize, sizeof( tsize ) );
len = strlen( fname );
memset( &fname[len],' ',8-len );
updateNHStuff( out, fname, desc );
close( out );
if( dllflag ) {
remove( dll );
rename( exe,dll );
myPrintf("Created \"%s\" (%ld + %ld = %ld bytes)\n", dll,
tsize,totalsize, tsize+totalsize );
} else {
myPrintf("Created \"%s\" (%ld + %ld = %ld bytes)\n", exe,
tsize,totalsize, tsize+totalsize );
}
return( 0 );
} /* main */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?