mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
14 KiB
631 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
main
|
|
|
|
Abstract:
|
|
|
|
framework and utility routines for cvtres
|
|
|
|
Author:
|
|
|
|
Sanford A. Staab (sanfords) 23-Apr-1990
|
|
|
|
Revision History:
|
|
|
|
01-Oct-1990 mikeke
|
|
Added support for conversion of win30 resources
|
|
|
|
19-May-1990 Steve Wood (stevewo)
|
|
Added the target machine switches, along with the debug switch.
|
|
|
|
23-Apr-1990 sanfords
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
|
|
#include <share.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "cvtres.h"
|
|
#include "rc.h"
|
|
#include "getmsg.h"
|
|
#include "msg.h"
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
char *szInFile;
|
|
char *szOutFile;
|
|
USHORT targetMachine = IMAGE_FILE_MACHINE_UNKNOWN;
|
|
USHORT targetRelocType;
|
|
BOOL fVerbose;
|
|
BOOL fWritable = TRUE;
|
|
|
|
#if DBG
|
|
BOOL fDebug;
|
|
#endif /* DBG */
|
|
|
|
|
|
void
|
|
usage(int rc)
|
|
{
|
|
printf(get_err(MSG_VERSION), VER_PRODUCTVERSION_STR);
|
|
puts(get_err(MSG_COPYRIGHT));
|
|
|
|
puts("usage: CVTRES [options] ResFile\n"
|
|
"\n"
|
|
" options:\n"
|
|
"\n"
|
|
#if DBG
|
|
" /DEBUG\n"
|
|
#endif /* DBG */
|
|
" /MACHINE:{IX86|MIPS|ALPHA|PPC}\n"
|
|
" /NOLOGO\n"
|
|
" /OUT:filename\n"
|
|
" /READONLY\n"
|
|
" /VERBOSE\n");
|
|
|
|
exit(rc);
|
|
}
|
|
|
|
|
|
void
|
|
_CRTAPI1 main(
|
|
IN int argc,
|
|
IN char *argv[]
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines options
|
|
locates and opens input files
|
|
reads input files
|
|
writes output files
|
|
exits
|
|
|
|
Exit Value:
|
|
|
|
0 on success
|
|
1 if error
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
char szDrive[_MAX_DRIVE];
|
|
char szDir[_MAX_DIR];
|
|
char szFname[_MAX_FNAME];
|
|
char szExt[_MAX_EXT];
|
|
char szInPath[_MAX_PATH];
|
|
char szOutPath[_MAX_PATH];
|
|
FILE *fh;
|
|
FILE *fhOut;
|
|
char *s1;
|
|
long lbytes;
|
|
BOOL result;
|
|
BOOL fNoLogo = FALSE;
|
|
BOOL fReproducible = FALSE;
|
|
DWORD timeDate;
|
|
|
|
SetErrorFile("cvtres.err", _pgmptr, 1);
|
|
|
|
if (argc == 1) {
|
|
usage(0);
|
|
}
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
s1 = argv[i];
|
|
|
|
if (*s1 == '/' || *s1 == '-') {
|
|
s1++;
|
|
|
|
if (!_strnicmp(s1, "machine:", 8)) {
|
|
s1 += 8;
|
|
|
|
if (!_stricmp(s1, "IX86") || !_stricmp(s1, "X86")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_I386;
|
|
targetRelocType = IMAGE_REL_I386_DIR32NB;
|
|
} else if (!_stricmp(s1, "MIPS")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_R4000;
|
|
targetRelocType = IMAGE_REL_MIPS_REFWORDNB;
|
|
} else if (!_stricmp(s1, "ALPHA")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_ALPHA;
|
|
targetRelocType = IMAGE_REL_ALPHA_REFLONGNB;
|
|
} else if (!_stricmp(s1, "PPC")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_POWERPC;
|
|
targetRelocType = IMAGE_REL_PPC_ADDR32NB;
|
|
} else {
|
|
usage(1);
|
|
}
|
|
} else if (!_stricmp(s1, "nologo")) {
|
|
fNoLogo = TRUE;
|
|
} else if (!_stricmp(s1, "o")) {
|
|
szOutFile = argv[++i];
|
|
} else if (!_strnicmp(s1, "out:", 4)) {
|
|
szOutFile = s1+4;
|
|
} else if (!_stricmp(s1, "readonly") || !_stricmp(s1, "r")) {
|
|
fWritable = FALSE;
|
|
} else if (!_stricmp(s1, "verbose") || !_stricmp(s1, "v")) {
|
|
fVerbose = TRUE;
|
|
} else if (!_stricmp(s1, "Brepro")) {
|
|
fReproducible = TRUE;
|
|
} else if (!_stricmp(s1, "I386")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_I386;
|
|
targetRelocType = IMAGE_REL_I386_DIR32NB;
|
|
} else if (!_stricmp(s1, "IX86")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_I386;
|
|
targetRelocType = IMAGE_REL_I386_DIR32NB;
|
|
} else if (!_stricmp(s1, "MIPS")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_R4000;
|
|
targetRelocType = IMAGE_REL_MIPS_REFWORDNB;
|
|
} else if (!_stricmp(s1, "ALPHA")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_ALPHA;
|
|
targetRelocType = IMAGE_REL_ALPHA_REFLONGNB;
|
|
} else if (!_stricmp(s1, "PPC")) {
|
|
targetMachine = IMAGE_FILE_MACHINE_POWERPC;
|
|
targetRelocType = IMAGE_REL_PPC_ADDR32NB;
|
|
#if DBG
|
|
} else if (!_stricmp(s1, "debug") || !_stricmp(s1, "d")) {
|
|
fDebug = TRUE;
|
|
fVerbose = TRUE;
|
|
#endif /* DBG */
|
|
} else {
|
|
usage(1);
|
|
}
|
|
} else {
|
|
szInFile = s1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure that we actually got a file
|
|
//
|
|
|
|
if (!szInFile) {
|
|
usage(1);
|
|
}
|
|
|
|
if (!fNoLogo) {
|
|
printf(get_err(MSG_VERSION), VER_PRODUCTVERSION_STR);
|
|
puts(get_err(MSG_COPYRIGHT));
|
|
}
|
|
|
|
if (targetMachine == IMAGE_FILE_MACHINE_UNKNOWN) {
|
|
WarningPrint(WARN_NOMACHINESPECIFIED,
|
|
#if defined(_M_IX86)
|
|
"IX86");
|
|
targetMachine = IMAGE_FILE_MACHINE_I386;
|
|
targetRelocType = IMAGE_REL_I386_DIR32NB;
|
|
#elif defined(_M_RX000)
|
|
"MIPS");
|
|
targetMachine = IMAGE_FILE_MACHINE_R4000;
|
|
targetRelocType = IMAGE_REL_MIPS_REFWORDNB;
|
|
#elif defined(_M_ALPHA)
|
|
"ALPHA");
|
|
targetMachine = IMAGE_FILE_MACHINE_ALPHA;
|
|
targetRelocType = IMAGE_REL_ALPHA_REFLONGNB;
|
|
#elif defined(_M_PPC)
|
|
"PPC");
|
|
targetMachine = IMAGE_FILE_MACHINE_POWERPC;
|
|
targetRelocType = IMAGE_REL_PPC_ADDR32NB;
|
|
#else
|
|
"unknown");
|
|
#endif
|
|
}
|
|
|
|
_splitpath(szInFile, szDrive, szDir, szFname, szExt);
|
|
|
|
if (szExt[0] == '\0') {
|
|
// If there is no extension, default to .res
|
|
|
|
_makepath(szInPath, szDrive, szDir, szFname, ".res");
|
|
|
|
szInFile = szInPath;
|
|
}
|
|
|
|
if ((fh = _fsopen(szInFile, "rb", _SH_DENYWR)) == NULL) {
|
|
ErrorPrint(ERR_CANTREADFILE, szInFile);
|
|
exit(1);
|
|
}
|
|
|
|
#if DBG
|
|
printf("Reading %s\n", szInFile);
|
|
#endif /* DBG */
|
|
|
|
lbytes = MySeek(fh, 0L, SEEK_END);
|
|
MySeek(fh, 0L, SEEK_SET);
|
|
|
|
if (szOutFile == NULL) {
|
|
// Default output file is input file with .obj extension
|
|
|
|
_makepath(szOutPath, szDrive, szDir, szFname, ".obj");
|
|
|
|
szOutFile = szOutPath;
|
|
}
|
|
|
|
if ((fhOut = _fsopen(szOutFile, "wb", _SH_DENYRW)) == NULL) {
|
|
ErrorPrint(ERR_CANTWRITEFILE, szOutFile);
|
|
exit(1);
|
|
}
|
|
|
|
#if DBG
|
|
printf("Writing %s\n", szOutFile);
|
|
#endif /* DBG */
|
|
|
|
_tzset();
|
|
// timeDate = (ULONG) time(NULL);
|
|
timeDate = (ULONG) (fReproducible ? -1 : time(NULL));
|
|
|
|
result = CvtRes(fh, fhOut, lbytes, fWritable, timeDate);
|
|
|
|
fclose(fh);
|
|
fclose(fhOut);
|
|
|
|
exit(result ? 0 : 1);
|
|
}
|
|
|
|
|
|
|
|
|
|
PVOID
|
|
MyAlloc(UINT nbytes)
|
|
{
|
|
UCHAR *s;
|
|
|
|
if ((s = (UCHAR*)calloc( 1, nbytes )) != NULL) {
|
|
return s;
|
|
}
|
|
|
|
ErrorPrint(ERR_OUTOFMEMORY, nbytes );
|
|
exit(1);
|
|
}
|
|
|
|
|
|
PVOID
|
|
MyFree( PVOID p )
|
|
{
|
|
if (p)
|
|
free( p );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
USHORT
|
|
MyReadWord(FILE *fh, USHORT*p)
|
|
{
|
|
UINT n1;
|
|
|
|
if ((n1 = fread(p, 1, sizeof(USHORT), fh)) != sizeof(USHORT)) {
|
|
ErrorPrint( ERR_FILEREADERR);
|
|
exit(1);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
UINT
|
|
MyRead(FILE *fh, PVOID p, UINT n )
|
|
{
|
|
UINT n1;
|
|
|
|
if ((n1 = fread( p, 1, n, fh)) != n) {
|
|
ErrorPrint( ERR_FILEREADERR );
|
|
exit(1);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
LONG
|
|
MyTell( FILE *fh )
|
|
{
|
|
long pos;
|
|
|
|
if ((pos = ftell( fh )) == -1) {
|
|
ErrorPrint(ERR_FILETELLERR );
|
|
exit(1);
|
|
}
|
|
|
|
return pos;
|
|
}
|
|
|
|
|
|
LONG
|
|
MySeek( FILE *fh, long pos, int cmd )
|
|
{
|
|
if ((pos = fseek( fh, pos, cmd )) == -1) {
|
|
ErrorPrint(ERR_FILESEEKERR );
|
|
exit(1);
|
|
}
|
|
|
|
return MyTell(fh);
|
|
}
|
|
|
|
|
|
ULONG
|
|
MoveFilePos( FILE *fh, USHORT pos, int alignment )
|
|
{
|
|
long newpos;
|
|
|
|
newpos = (long)pos;
|
|
newpos <<= alignment;
|
|
return MySeek( fh, newpos, SEEK_SET );
|
|
}
|
|
|
|
|
|
UINT
|
|
MyWrite( FILE *fh, PVOID p, UINT n )
|
|
{
|
|
ULONG n1;
|
|
|
|
if ((n1 = fwrite( p, 1, n, fh )) != n) {
|
|
ErrorPrint(ERR_FILEWRITEERR );
|
|
exit(1);
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
#undef BUFSIZE
|
|
#define BUFSIZE 1024
|
|
|
|
int
|
|
MyCopy( FILE *srcfh, FILE *dstfh, ULONG nbytes )
|
|
{
|
|
static UCHAR buffer[ BUFSIZE ];
|
|
UINT n;
|
|
ULONG cb=0L;
|
|
|
|
while (nbytes) {
|
|
if (nbytes <= BUFSIZE)
|
|
n = (UINT)nbytes;
|
|
else
|
|
n = BUFSIZE;
|
|
nbytes -= n;
|
|
|
|
if (!MyRead( srcfh, buffer, n )) {
|
|
cb += n;
|
|
MyWrite( dstfh, buffer, n );
|
|
}
|
|
else {
|
|
return cb;
|
|
}
|
|
}
|
|
return cb;
|
|
}
|
|
|
|
|
|
void
|
|
ErrorPrint(
|
|
USHORT errnum,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
va_start(va, errnum);
|
|
|
|
printf(get_err(MSG_ERROR), errnum, ' ');
|
|
|
|
vprintf(get_err(errnum), va);
|
|
printf("\n");
|
|
|
|
va_end(va);
|
|
}
|
|
|
|
void
|
|
WarningPrint(
|
|
USHORT errnum,
|
|
...
|
|
)
|
|
{
|
|
va_list va;
|
|
va_start(va, errnum);
|
|
|
|
printf(get_err(MSG_WARNING), errnum, ' ');
|
|
|
|
vprintf(get_err(errnum), va);
|
|
printf("\n");
|
|
|
|
va_end(va);
|
|
}
|
|
|
|
#if 0
|
|
|
|
/***
|
|
*splitpath.c - break down path name into components
|
|
*
|
|
* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* To provide support for accessing the individual components of an
|
|
* arbitrary path name
|
|
*
|
|
*Revision History:
|
|
* 06-14-87 DFW initial implementation
|
|
* 09-23-87 JCR Removed 'const' from declarations (fixed cl warnings)
|
|
* 12-11-87 JCR Added "_LOAD_DS" to declaration
|
|
* 11-20-89 GJF Fixed indents, copyright. Added const attribute to
|
|
* type of path.
|
|
* 03-15-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
|
|
* <cruntime.h>.
|
|
* 07-25-90 SBM Removed redundant include (stdio.h), replaced local
|
|
* MIN macro with standard min macro
|
|
* 10-04-90 GJF New-style function declarator.
|
|
* 01-22-91 GJF ANSI naming.
|
|
* 11-20-92 KRS Port _MBCS support from 16-bit tree.
|
|
* 05-12-93 KRS Add fix for MBCS max path handling.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
/***
|
|
*_splitpath() - split a path name into its individual components
|
|
*
|
|
*Purpose:
|
|
* to split a path name into its individual components
|
|
*
|
|
*Entry:
|
|
* path - pointer to path name to be parsed
|
|
* drive - pointer to buffer for drive component, if any
|
|
* dir - pointer to buffer for subdirectory component, if any
|
|
* fname - pointer to buffer for file base name component, if any
|
|
* ext - pointer to buffer for file name extension component, if any
|
|
*
|
|
*Exit:
|
|
* drive - pointer to drive string. Includes ':' if a drive was given.
|
|
* dir - pointer to subdirectory string. Includes leading and trailing
|
|
* '/' or '\', if any.
|
|
* fname - pointer to file base name
|
|
* ext - pointer to file extension, if any. Includes leading '.'.
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void _CRTAPI1 _splitpath (
|
|
register const char *path,
|
|
char *drive,
|
|
char *dir,
|
|
char *fname,
|
|
char *ext
|
|
)
|
|
{
|
|
register char *p;
|
|
char *last_slash = NULL, *dot = NULL;
|
|
unsigned len;
|
|
|
|
UINT uiCodePage = GetACP();
|
|
|
|
/* we assume that the path argument has the following form, where any
|
|
* or all of the components may be missing.
|
|
*
|
|
* <drive><dir><fname><ext>
|
|
*
|
|
* and each of the components has the following expected form(s)
|
|
*
|
|
* drive:
|
|
* 0 to _MAX_DRIVE-1 characters, the last of which, if any, is a
|
|
* ':'
|
|
* dir:
|
|
* 0 to _MAX_DIR-1 characters in the form of an absolute path
|
|
* (leading '/' or '\') or relative path, the last of which, if
|
|
* any, must be a '/' or '\'. E.g -
|
|
* absolute path:
|
|
* \top\next\last\ ; or
|
|
* /top/next/last/
|
|
* relative path:
|
|
* top\next\last\ ; or
|
|
* top/next/last/
|
|
* Mixed use of '/' and '\' within a path is also tolerated
|
|
* fname:
|
|
* 0 to _MAX_FNAME-1 characters not including the '.' character
|
|
* ext:
|
|
* 0 to _MAX_EXT-1 characters where, if any, the first must be a
|
|
* '.'
|
|
*
|
|
*/
|
|
|
|
/* extract drive letter and :, if any */
|
|
|
|
if (*(path + _MAX_DRIVE - 2) == ':') {
|
|
if (drive) {
|
|
strncpy(drive, path, _MAX_DRIVE - 1);
|
|
*(drive + _MAX_DRIVE-1) = '\0';
|
|
}
|
|
path += _MAX_DRIVE - 1;
|
|
}
|
|
else if (drive) {
|
|
*drive = '\0';
|
|
}
|
|
|
|
/* extract path string, if any. Path now points to the first character
|
|
* of the path, if any, or the filename or extension, if no path was
|
|
* specified. Scan ahead for the last occurence, if any, of a '/' or
|
|
* '\' path separator character. If none is found, there is no path.
|
|
* We will also note the last '.' character found, if any, to aid in
|
|
* handling the extension.
|
|
*/
|
|
|
|
for (last_slash = NULL, p = (char *)path; *p; p++) {
|
|
if (IsDBCSLeadByteEx(uiCodePage, *p))
|
|
p++;
|
|
else {
|
|
if (*p == '/' || *p == '\\')
|
|
/* point to one beyond for later copy */
|
|
last_slash = p + 1;
|
|
else if (*p == '.')
|
|
dot = p;
|
|
}
|
|
}
|
|
|
|
if (last_slash) {
|
|
|
|
/* found a path - copy up through last_slash or max. characters
|
|
* allowed, whichever is smaller
|
|
*/
|
|
|
|
if (dir) {
|
|
len = __min((last_slash - path), (_MAX_DIR - 1));
|
|
strncpy(dir, path, len);
|
|
*(dir + len) = '\0';
|
|
}
|
|
path = last_slash;
|
|
}
|
|
else if (dir) {
|
|
|
|
/* no path found */
|
|
|
|
*dir = '\0';
|
|
}
|
|
|
|
/* extract file name and extension, if any. Path now points to the
|
|
* first character of the file name, if any, or the extension if no
|
|
* file name was given. Dot points to the '.' beginning the extension,
|
|
* if any.
|
|
*/
|
|
|
|
if (dot && (dot >= path)) {
|
|
/* found the marker for an extension - copy the file name up to
|
|
* the '.'.
|
|
*/
|
|
if (fname) {
|
|
len = __min((dot - path), (_MAX_FNAME - 1));
|
|
strncpy(fname, path, len);
|
|
*(fname + len) = '\0';
|
|
}
|
|
/* now we can get the extension - remember that p still points
|
|
* to the terminating nul character of path.
|
|
*/
|
|
if (ext) {
|
|
len = __min((p - dot), (_MAX_EXT - 1));
|
|
strncpy(ext, dot, len);
|
|
*(ext + len) = '\0';
|
|
}
|
|
}
|
|
else {
|
|
/* found no extension, give empty extension and copy rest of
|
|
* string into fname.
|
|
*/
|
|
if (fname) {
|
|
len = __min((p - path), (_MAX_FNAME - 1));
|
|
strncpy(fname, path, len);
|
|
*(fname + len) = '\0';
|
|
}
|
|
if (ext) {
|
|
*ext = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|