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.
1747 lines
54 KiB
1747 lines
54 KiB
/*
|
|
* Utility program to munge a set of files, translating names from
|
|
* one form to another. Usage:
|
|
*
|
|
* munge scriptFile files...
|
|
*
|
|
* where the first parameter is the name of a file that consists of
|
|
* one or more lines of the following format:
|
|
*
|
|
* oldName newName
|
|
*
|
|
* and the remaining parameters are the names of the files to munge.
|
|
* Each file is _read into memory, scanned once, where each occurence
|
|
* of an oldName string is replaced by its corresponding newName.
|
|
* If any changes are made to a file, the old version is RMed and
|
|
* the new version written out under the same name.
|
|
*
|
|
*/
|
|
|
|
#include "munge.h"
|
|
|
|
BOOL SymbolsInserted;
|
|
BOOL InitTokenMappingTable( void );
|
|
BOOL SaveTokenMapping( char *, char * );
|
|
char *FindTokenMapping( char * );
|
|
|
|
#define MAXFILESIZE 0x1000000L
|
|
char *InputFileBuf;
|
|
char *OutputFileBuf;
|
|
int fClean;
|
|
int fQuery;
|
|
int fFileOnly;
|
|
int fRecurse;
|
|
int fUseAttrib;
|
|
int fUseSLM;
|
|
int fForceSLM;
|
|
int fTrustMe;
|
|
int fVerbose;
|
|
int fSummary;
|
|
int fRemoveDuplicateCR;
|
|
int fRemoveImbeddedNulls;
|
|
int fTruncateWithCtrlZ;
|
|
int fInsideQuotes;
|
|
int fInsideComments;
|
|
int fNeuter;
|
|
int fCaseSensitive;
|
|
int fEntireLine;
|
|
|
|
#define MAX_LITERAL_STRINGS 64
|
|
|
|
void
|
|
DoFiles(
|
|
char *p,
|
|
struct findType *b,
|
|
void *Args
|
|
);
|
|
|
|
unsigned long NumberOfLiteralStrings;
|
|
char *LiteralStrings[ MAX_LITERAL_STRINGS ];
|
|
unsigned long LiteralStringsLength[ MAX_LITERAL_STRINGS ];
|
|
char *NewLiteralStrings[ MAX_LITERAL_STRINGS ];
|
|
char LeadingLiteralChars[ MAX_LITERAL_STRINGS+1 ];
|
|
|
|
unsigned long NumberOfFileExtensions = 0;
|
|
char *FileExtensions[ 64 ];
|
|
|
|
unsigned long NumberOfFileNames = 0;
|
|
char *FileNames[ 64 ];
|
|
|
|
unsigned long NumberOfFileNameAndExts = 0;
|
|
char *FileNameAndExts[ 64 ];
|
|
|
|
|
|
char *UndoScriptFileName;
|
|
FILE *UndoScriptFile;
|
|
int UndoCurDirCount;
|
|
|
|
void
|
|
DisplayFilePatterns( void );
|
|
|
|
char *
|
|
PushCurrentDirectory(
|
|
char *NewCurrentDirectory
|
|
);
|
|
|
|
void
|
|
PopCurrentDirectory(
|
|
char *OldCurrentDirectory
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
CreateSymbolTable(
|
|
IN ULONG NumberOfBuckets,
|
|
IN ULONG MaxSymbolTableSize,
|
|
OUT PVOID *SymbolTableHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
AddSymbolToSymbolTable(
|
|
IN PVOID SymbolTableHandle,
|
|
IN PUNICODE_STRING SymbolName,
|
|
IN ULONG_PTR *SymbolValue OPTIONAL
|
|
);
|
|
|
|
NTSTATUS
|
|
LookupSymbolInSymbolTable(
|
|
IN PVOID SymbolTableHandle,
|
|
IN PUNICODE_STRING SymbolName,
|
|
OUT ULONG_PTR *SymbolValue OPTIONAL
|
|
);
|
|
|
|
BOOL
|
|
myread( int fh, unsigned long cb )
|
|
{
|
|
HANDLE InputFileMapping;
|
|
|
|
InputFileMapping = CreateFileMapping( (HANDLE)_get_osfhandle( fh ),
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
cb,
|
|
NULL
|
|
);
|
|
|
|
if (InputFileMapping == NULL) {
|
|
if (cb != 0) {
|
|
fprintf( stderr, "Unable to map file (%d) - ", GetLastError() );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
InputFileBuf = MapViewOfFile( InputFileMapping,
|
|
FILE_MAP_READ,
|
|
0,
|
|
0,
|
|
cb
|
|
);
|
|
|
|
CloseHandle( InputFileMapping );
|
|
if (InputFileBuf == NULL) {
|
|
if (cb != 0) {
|
|
fprintf( stderr, "Unable to map view (%d) - ", GetLastError() );
|
|
}
|
|
|
|
CloseHandle( InputFileMapping );
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
unsigned long mywrite( int fh, char *s, unsigned long cb )
|
|
{
|
|
unsigned long cbWritten;
|
|
|
|
if (!WriteFile( (HANDLE)_get_osfhandle( fh ), s, cb, &cbWritten, NULL )) {
|
|
printf( "(%d)", GetLastError() );
|
|
return 0L;
|
|
} else {
|
|
return cbWritten;
|
|
}
|
|
}
|
|
|
|
|
|
static char lineBuf[ 1024 ];
|
|
|
|
ReadScriptFile( s )
|
|
char *s;
|
|
{
|
|
FILE *fh;
|
|
int lineNum, result;
|
|
char *pOldName, *pNewName, *pEnd;
|
|
unsigned n;
|
|
char LeadingChar, QuoteChar, SaveChar;
|
|
|
|
NumberOfLiteralStrings = 0;
|
|
|
|
n = 0;
|
|
fprintf( stderr, "Reading script file - %s", s );
|
|
if ( !( fh = fopen( s, "r" ) ) ) {
|
|
fprintf( stderr, " *** unable to open\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
result = TRUE;
|
|
lineNum = -1;
|
|
while ( pOldName = fgets( lineBuf, sizeof( lineBuf ), fh ) ) {
|
|
lineNum++;
|
|
while ( *pOldName == ' ' )
|
|
pOldName++;
|
|
|
|
if (*pOldName == '-' && (pOldName[1] == 'f' || pOldName[1] == 'F')) {
|
|
pOldName += 2;
|
|
while (*pOldName) {
|
|
while (*pOldName == ' ') {
|
|
pOldName++;
|
|
}
|
|
|
|
pEnd = pOldName;
|
|
while (*pEnd > ' ') {
|
|
pEnd++;
|
|
}
|
|
SaveChar = *pEnd;
|
|
*pEnd = '\0';
|
|
|
|
if (*pOldName == '.') {
|
|
pNewName = MakeStr( ++pOldName );
|
|
if (pNewName)
|
|
_strlwr(pNewName);
|
|
FileExtensions[ NumberOfFileExtensions++ ] = pNewName;
|
|
} else
|
|
if (pEnd > pOldName && pEnd[ -1 ] == '.') {
|
|
pEnd[ - 1 ] = '\0';
|
|
pNewName = MakeStr(pOldName);
|
|
if (pNewName)
|
|
_strlwr(pNewName);
|
|
FileNames[ NumberOfFileNames++ ] = pNewName;
|
|
} else {
|
|
pNewName = MakeStr(pOldName);
|
|
if (pNewName)
|
|
_strlwr(pNewName);
|
|
FileNameAndExts[ NumberOfFileNameAndExts++ ] = pNewName;
|
|
}
|
|
|
|
*pEnd = SaveChar;
|
|
pOldName = pEnd;
|
|
}
|
|
} else
|
|
if (*pOldName == '"' || *pOldName == '\'') {
|
|
if (NumberOfLiteralStrings >= MAX_LITERAL_STRINGS) {
|
|
fprintf( stderr, " *** too many literal strings\n" );
|
|
fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
QuoteChar = *pOldName;
|
|
LeadingChar = *++pOldName;
|
|
pNewName = pOldName;
|
|
while (*pNewName >= ' ' && *pNewName != QuoteChar) {
|
|
pNewName++;
|
|
}
|
|
|
|
if (*pNewName != QuoteChar) {
|
|
fprintf( stderr, " *** invalid literal string\n" );
|
|
fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
|
|
result = FALSE;
|
|
continue;
|
|
}
|
|
|
|
*pNewName++ = '\0';
|
|
while ( *pNewName == ' ' )
|
|
pNewName++;
|
|
|
|
if (*pNewName != QuoteChar) {
|
|
if (!fQuery) {
|
|
fprintf( stderr, " *** invalid literal string\n" );
|
|
fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
|
|
result = FALSE;
|
|
continue;
|
|
}
|
|
} else {
|
|
PUCHAR pDest, pSrc;
|
|
BOOL fEscaped = FALSE;
|
|
|
|
pEnd = ++pNewName;
|
|
pDest = pSrc = pEnd;
|
|
|
|
while ((*pSrc >= ' ') && ((*pSrc != QuoteChar) || fEscaped)) {
|
|
if (fEscaped) {
|
|
switch(pSrc[0]) {
|
|
case 'n':
|
|
*pDest++ = '\r';
|
|
*pDest++ = '\n';
|
|
break;
|
|
default:
|
|
*pDest++ = *pSrc;
|
|
break;
|
|
}
|
|
fEscaped = FALSE;
|
|
} else {
|
|
if (pSrc[0] == '\\') {
|
|
fEscaped = TRUE;
|
|
} else {
|
|
*pDest++ = *pSrc;
|
|
}
|
|
}
|
|
pSrc++;
|
|
}
|
|
|
|
pEnd = pSrc;
|
|
|
|
if (*pEnd != QuoteChar) {
|
|
fprintf( stderr, " *** invalid literal string\n" );
|
|
fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
|
|
result = FALSE;
|
|
continue;
|
|
}
|
|
*pDest = '\0';
|
|
}
|
|
|
|
LiteralStrings[ NumberOfLiteralStrings ] = MakeStr( ++pOldName );
|
|
LiteralStringsLength[ NumberOfLiteralStrings ] = strlen( pOldName );
|
|
NewLiteralStrings[ NumberOfLiteralStrings ] = MakeStr( pNewName );
|
|
LeadingLiteralChars[ NumberOfLiteralStrings ] = LeadingChar;
|
|
NumberOfLiteralStrings += 1;
|
|
} else {
|
|
pNewName = pOldName;
|
|
while ( *pNewName != '\0' && *pNewName != ' ' ) {
|
|
pNewName += 1;
|
|
}
|
|
|
|
if (*pNewName == '\0') {
|
|
if (!fQuery) {
|
|
if (result)
|
|
fprintf( stderr, " *** invalid script file\n" );
|
|
fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
|
|
result = FALSE;
|
|
continue;
|
|
}
|
|
|
|
while (pNewName > pOldName && pNewName[ -1 ] < ' ') {
|
|
*--pNewName = '\0';
|
|
}
|
|
|
|
pNewName = MakeStr( pOldName );
|
|
} else {
|
|
*pNewName++ = 0;
|
|
while ( *pNewName == ' ' )
|
|
pNewName++;
|
|
|
|
pEnd = pNewName;
|
|
while ( *pEnd > ' ' )
|
|
pEnd++;
|
|
*pEnd = 0;
|
|
pNewName = MakeStr( pNewName );
|
|
}
|
|
|
|
if (!pNewName || !SaveTokenMapping( pOldName, pNewName )) {
|
|
if (result)
|
|
fprintf( stderr, " *** out of memory\n" );
|
|
if (pNewName) {
|
|
free(pNewName);
|
|
}
|
|
fprintf( stderr, "%s(%d) - can't add symbol '%s'\n", s, lineNum, pOldName );
|
|
result = FALSE;
|
|
} else {
|
|
SymbolsInserted = TRUE;
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose( fh );
|
|
if (result) {
|
|
fprintf( stderr, " %d tokens", n );
|
|
if (NumberOfLiteralStrings) {
|
|
fprintf( stderr, " and %d literal strings\n", NumberOfLiteralStrings );
|
|
} else {
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
|
|
if (!NumberOfFileExtensions && !NumberOfFileNames && !NumberOfFileNameAndExts) {
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "asm";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "bat";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "c";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "cli";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "cpp";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "cxx";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "def";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "dlg";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "h";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "htm";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "hpj";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "hxx";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "idl";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "inc";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "inf";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "lic";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "mak";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "mc";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "odl";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "rc";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "rcv";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "reg";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "s";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "src";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "srv";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "tk";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "w";
|
|
FileExtensions[ NumberOfFileExtensions++ ] = "x";
|
|
FileNameAndExts[ NumberOfFileNameAndExts++ ] = "makefil0";
|
|
FileNameAndExts[ NumberOfFileNameAndExts++ ] = "makefile";
|
|
FileNameAndExts[ NumberOfFileNameAndExts++ ] = "sources";
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
int
|
|
MungeFile(
|
|
int fRepeatMunge,
|
|
char *FileName,
|
|
char *OldBuf,
|
|
unsigned long OldSize,
|
|
char *NewBuf,
|
|
unsigned long MaxNewSize,
|
|
unsigned long *FinalNewSize
|
|
)
|
|
{
|
|
unsigned long NewSize = MaxNewSize;
|
|
unsigned Changes = 0;
|
|
unsigned LineNumber;
|
|
char c, *Identifier, *BegLine, *EndLine, *OrigOldBuf;
|
|
char IdentifierBuffer[ 256 ];
|
|
char *p, *p1;
|
|
int i, j, k;
|
|
BOOL TruncatedByCtrlZ;
|
|
BOOL ImbeddedNullsStripped;
|
|
BOOL DuplicateCRStripped;
|
|
BOOL InSingleQuotes;
|
|
BOOL InDoubleQuotes;
|
|
BOOL Escape = FALSE;
|
|
BOOL Star = FALSE;
|
|
BOOL Backslash = FALSE;
|
|
BOOL Pound = FALSE;
|
|
BOOL Semi = FALSE;
|
|
BOOL LastEscape;
|
|
BOOL LastStar;
|
|
BOOL LastBackslash;
|
|
BOOL LastPound;
|
|
BOOL LastSemi;
|
|
BOOL SkipChar;
|
|
BOOL InLineComment;
|
|
BOOL InComment;
|
|
|
|
*FinalNewSize = 0;
|
|
LineNumber = 1;
|
|
TruncatedByCtrlZ = FALSE;
|
|
ImbeddedNullsStripped = FALSE;
|
|
DuplicateCRStripped = FALSE;
|
|
InSingleQuotes = FALSE;
|
|
InDoubleQuotes = FALSE;
|
|
InLineComment = FALSE;
|
|
InComment = FALSE;
|
|
LastEscape = FALSE;
|
|
LastStar = FALSE;
|
|
LastBackslash = FALSE;
|
|
OrigOldBuf = OldBuf;
|
|
|
|
while (OldSize) {
|
|
OldSize--;
|
|
c = *OldBuf++;
|
|
if (c == '\r') {
|
|
while (OldSize && *OldBuf == '\r') {
|
|
DuplicateCRStripped = TRUE;
|
|
OldSize--;
|
|
c = *OldBuf++;
|
|
}
|
|
}
|
|
|
|
if (c == 0x1A) {
|
|
TruncatedByCtrlZ = TRUE;
|
|
break;
|
|
}
|
|
|
|
SkipChar = FALSE;
|
|
|
|
if ( !fInsideQuotes || !fInsideComments ) {
|
|
LastEscape = Escape;
|
|
LastStar = Star;
|
|
LastBackslash = Backslash;
|
|
LastPound = Pound;
|
|
LastSemi = Semi;
|
|
|
|
Escape = (c == '\\');
|
|
Star = (c == '*' );
|
|
Backslash = (c == '/' );
|
|
Pound = (c == '#' );
|
|
Semi = (c == ';' );
|
|
|
|
if ( Escape && LastEscape ) { // two in a row don't mean escape
|
|
Escape = FALSE;
|
|
}
|
|
|
|
if ( c == '\r' || c == '\n' ) {
|
|
InLineComment = FALSE;
|
|
}
|
|
|
|
|
|
// Don't process Include or Pragma directives
|
|
if ( LastPound && OldSize > 6 ) {
|
|
if ( !strncmp(OldBuf-1,"include",7)
|
|
|| !strncmp(OldBuf-1,"pragma",6) ) {
|
|
InLineComment = TRUE;
|
|
}
|
|
}
|
|
|
|
if (c == '"' && !InSingleQuotes && !LastEscape
|
|
&& !InLineComment && !InComment ) {
|
|
InDoubleQuotes = !InDoubleQuotes;
|
|
if ( fNeuter ) {
|
|
if ( InDoubleQuotes ) {
|
|
if ( NewSize < 5 ) {
|
|
return( -1 );
|
|
}
|
|
strcpy(NewBuf,"TEXT(");
|
|
NewBuf+=5;
|
|
NewSize -= 5;
|
|
} else {
|
|
if ( NewSize < 1 ) {
|
|
return( -1 );
|
|
}
|
|
*NewBuf++ = '"';
|
|
NewSize--;
|
|
c = ')';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (c == '\'' && !InDoubleQuotes && !LastEscape
|
|
&& !InLineComment && !InComment ) {
|
|
InSingleQuotes = !InSingleQuotes;
|
|
if ( fNeuter ) {
|
|
if ( InSingleQuotes ) {
|
|
if ( NewSize < 5 ) {
|
|
return( -1 );
|
|
}
|
|
strcpy(NewBuf,"TEXT(");
|
|
NewBuf+=5;
|
|
NewSize -= 5;
|
|
} else {
|
|
if ( NewSize < 1 ) {
|
|
return( -1 );
|
|
}
|
|
*NewBuf++ = '\'';
|
|
NewSize--;
|
|
c = ')';
|
|
}
|
|
}
|
|
}
|
|
if ( !InDoubleQuotes && !InSingleQuotes
|
|
&& !InLineComment && !InComment ) {
|
|
if ( LastBackslash ) {
|
|
switch (c) {
|
|
case '*': InComment = TRUE; break;
|
|
case '/': InLineComment = TRUE; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( InComment && LastStar && Backslash ) {
|
|
InComment = FALSE;
|
|
}
|
|
|
|
if ( !fInsideQuotes && ( InSingleQuotes || InDoubleQuotes ) ) {
|
|
SkipChar = TRUE;
|
|
} else
|
|
if ( !fInsideComments && ( InLineComment || InComment ) ) {
|
|
SkipChar = TRUE;
|
|
}
|
|
}
|
|
|
|
if (c != 0 && NumberOfLiteralStrings != 0 && !SkipChar ) {
|
|
p = LeadingLiteralChars;
|
|
while (p = strchr( p, c )) {
|
|
i = (int)(p - LeadingLiteralChars);
|
|
p++;
|
|
if (OldSize >= LiteralStringsLength[ i ]) {
|
|
p1 = IdentifierBuffer;
|
|
Identifier = OldBuf;
|
|
j = LiteralStringsLength[ i ];
|
|
while (j--) {
|
|
*p1++ = *Identifier++;
|
|
}
|
|
*p1 = '\0';
|
|
|
|
if (!strcmp( LiteralStrings[ i ], IdentifierBuffer )) {
|
|
BegLine = OldBuf - 1;
|
|
OldSize -= LiteralStringsLength[ i ];
|
|
OldBuf = Identifier;
|
|
p1 = NewLiteralStrings[ i ];
|
|
|
|
if (!fRepeatMunge && !fSummary) {
|
|
if (fFileOnly) {
|
|
if (Changes == 0) { // Display just file name on first match
|
|
printf( "%s\n", FileName );
|
|
}
|
|
} else {
|
|
printf( "%s(%d) : ",
|
|
FileName,
|
|
LineNumber
|
|
);
|
|
if (fQuery) {
|
|
EndLine = BegLine;
|
|
while (*EndLine != '\0' && *EndLine != '\n') {
|
|
EndLine += 1;
|
|
}
|
|
if (fEntireLine) {
|
|
while (BegLine > OrigOldBuf && *BegLine != '\n') {
|
|
BegLine -= 1;
|
|
}
|
|
if (*BegLine == '\n') {
|
|
BegLine += 1;
|
|
}
|
|
}
|
|
|
|
printf( "%.*s\n", EndLine - BegLine, BegLine );
|
|
} else {
|
|
printf( "Matched \"%c%s\", replace with \"%s\"\n",
|
|
c,
|
|
LiteralStrings[ i ],
|
|
p1
|
|
);
|
|
}
|
|
}
|
|
fflush( stdout );
|
|
}
|
|
|
|
Changes++;
|
|
while (*p1) {
|
|
if (NewSize--) {
|
|
*NewBuf++ = *p1++;
|
|
} else {
|
|
return( -1 );
|
|
}
|
|
}
|
|
|
|
c = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
p = NULL;
|
|
}
|
|
|
|
if (SymbolsInserted && (p == NULL) && iscsymf( c )) {
|
|
BegLine = OldBuf - 1;
|
|
Identifier = IdentifierBuffer;
|
|
k = sizeof( IdentifierBuffer ) - 1;
|
|
while (iscsym( c )) {
|
|
if (k) {
|
|
*Identifier++ = c;
|
|
k--;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
if (OldSize--) {
|
|
c = *OldBuf++;
|
|
} else {
|
|
// OldSize will get updated below...
|
|
c = '\0';
|
|
}
|
|
}
|
|
|
|
c = '\0'; // No character to add to output stream
|
|
|
|
--OldBuf; // Went a little too far
|
|
OldSize++;
|
|
|
|
*Identifier++ = 0;
|
|
|
|
if (k == 0 || (Identifier = FindTokenMapping( IdentifierBuffer )) == NULL || SkipChar ) {
|
|
Identifier = IdentifierBuffer;
|
|
} else {
|
|
if (!fRepeatMunge && !fSummary) {
|
|
if (fFileOnly) {
|
|
if (Changes == 0) { // Display just file name on first match
|
|
printf( "%s\n", FileName );
|
|
}
|
|
} else {
|
|
printf( "%s(%d) : ", FileName, LineNumber );
|
|
if (fQuery) {
|
|
EndLine = BegLine;
|
|
while (*EndLine != '\0' && *EndLine != '\r' && *EndLine != '\n') {
|
|
EndLine += 1;
|
|
}
|
|
if (*EndLine == '\0') {
|
|
EndLine -= 1;
|
|
}
|
|
if (*EndLine == '\n') {
|
|
EndLine -= 1;
|
|
}
|
|
if (*EndLine == '\r') {
|
|
EndLine -= 1;
|
|
}
|
|
|
|
if (fEntireLine) {
|
|
while (BegLine > OrigOldBuf && *BegLine != '\n') {
|
|
BegLine -= 1;
|
|
}
|
|
if (*BegLine == '\n') {
|
|
BegLine += 1;
|
|
}
|
|
}
|
|
|
|
printf( "%.*s", EndLine - BegLine + 1, BegLine );
|
|
} else {
|
|
printf( "Matched %s replace with %s", IdentifierBuffer, Identifier );
|
|
}
|
|
|
|
printf( "\n" );
|
|
}
|
|
|
|
fflush( stdout );
|
|
}
|
|
|
|
Changes++;
|
|
}
|
|
|
|
while (*Identifier) {
|
|
if (NewSize--) {
|
|
*NewBuf++ = *Identifier++;
|
|
} else {
|
|
return( -1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (c == '\n') {
|
|
LineNumber++;
|
|
}
|
|
|
|
if (c != '\0') {
|
|
if (NewSize--) {
|
|
*NewBuf++ = c;
|
|
} else {
|
|
return( -1 );
|
|
}
|
|
} else {
|
|
ImbeddedNullsStripped = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!Changes && fClean) {
|
|
if (fTruncateWithCtrlZ && TruncatedByCtrlZ) {
|
|
if (!fRepeatMunge && !fSummary) {
|
|
printf( "%s(%d) : File truncated by Ctrl-Z\n",
|
|
FileName,
|
|
LineNumber
|
|
);
|
|
fflush( stdout );
|
|
}
|
|
|
|
Changes++;
|
|
}
|
|
|
|
if (fRemoveImbeddedNulls && ImbeddedNullsStripped) {
|
|
if (!fRepeatMunge && !fSummary) {
|
|
printf( "%s(%d) : Imbedded null characters removed.\n",
|
|
FileName,
|
|
LineNumber
|
|
);
|
|
fflush( stdout );
|
|
}
|
|
|
|
Changes++;
|
|
}
|
|
|
|
if (fRemoveDuplicateCR && DuplicateCRStripped) {
|
|
if (!fRepeatMunge && !fSummary) {
|
|
printf( "%s(%d) : Duplicate Carriage returns removed.\n",
|
|
FileName,
|
|
LineNumber
|
|
);
|
|
fflush( stdout );
|
|
}
|
|
|
|
Changes++;
|
|
}
|
|
}
|
|
|
|
*FinalNewSize = MaxNewSize - NewSize;
|
|
return( Changes );
|
|
}
|
|
|
|
|
|
typedef struct _MUNGED_LIST_ELEMENT {
|
|
struct _MUNGED_LIST_ELEMENT *Next;
|
|
char *FileName;
|
|
int NumberOfChanges;
|
|
} MUNGED_LIST_ELEMENT, *PMUNGED_LIST_ELEMENT;
|
|
|
|
PMUNGED_LIST_ELEMENT MungedListHead;
|
|
|
|
BOOL
|
|
RememberMunge(
|
|
char *FileName,
|
|
int NumberOfChanges
|
|
);
|
|
|
|
BOOL
|
|
CheckIfMungedAlready(
|
|
char *FileName
|
|
);
|
|
|
|
void
|
|
DumpMungedList( void );
|
|
|
|
BOOL
|
|
RememberMunge(
|
|
char *FileName,
|
|
int NumberOfChanges
|
|
)
|
|
{
|
|
PMUNGED_LIST_ELEMENT p;
|
|
|
|
p = (PMUNGED_LIST_ELEMENT)malloc( sizeof( *p ) + strlen( FileName ) + 4 );
|
|
if (p == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
p->FileName = (char *)(p + 1);
|
|
strcpy( p->FileName, FileName );
|
|
p->NumberOfChanges = NumberOfChanges;
|
|
p->Next = MungedListHead;
|
|
MungedListHead = p;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CheckIfMungedAlready(
|
|
char *FileName
|
|
)
|
|
{
|
|
PMUNGED_LIST_ELEMENT p;
|
|
|
|
p = MungedListHead;
|
|
while (p) {
|
|
if (!strcmp( FileName, p->FileName )) {
|
|
return TRUE;
|
|
}
|
|
|
|
p = p->Next;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
DumpMungedList( void )
|
|
{
|
|
PMUNGED_LIST_ELEMENT p, p1;
|
|
|
|
if (!fSummary) {
|
|
return;
|
|
}
|
|
|
|
p = MungedListHead;
|
|
while (p) {
|
|
p1 = p;
|
|
printf( "%u changes made to the file %s(1).\n", p->NumberOfChanges, p->FileName );
|
|
p = p->Next;
|
|
free( (char *)p1 );
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DoFile( p )
|
|
char *p;
|
|
{
|
|
int fh, n;
|
|
unsigned long oldSize;
|
|
unsigned long newSize;
|
|
int count, rc;
|
|
char newName[ 128 ];
|
|
char bakName[ 128 ];
|
|
char CommandLine[ 192 ];
|
|
char *s, *CurrentDirectory;
|
|
DWORD dwFileAttributes;
|
|
int fRepeatMunge;
|
|
|
|
if (CheckIfMungedAlready( p )) {
|
|
return;
|
|
}
|
|
|
|
if (fVerbose)
|
|
fprintf( stderr, "Scanning %s\n", p );
|
|
|
|
strcpy( &newName[ 0 ], p );
|
|
strcpy( &bakName[ 0 ], p );
|
|
for (n = strlen( &newName[ 0 ] )-1; n > 0; n--) {
|
|
if (newName[ n ] == '.') {
|
|
break;
|
|
} else
|
|
if (newName[ n ] == '\\') {
|
|
n = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (n == 0) {
|
|
n = strlen( &newName[ 0 ] );
|
|
}
|
|
strcpy( &newName[ n ], ".mge" );
|
|
strcpy( &bakName[ n ], ".bak" );
|
|
fRepeatMunge = FALSE;
|
|
|
|
RepeatMunge:
|
|
if ( (fh = _open( p, O_BINARY )) == -1) {
|
|
fprintf( stderr, "%s - unable to open\n", p );
|
|
return;
|
|
}
|
|
|
|
oldSize = _lseek( fh, 0L, 2 );
|
|
if (_lseek( fh, 0L, 0 ) == -1) {
|
|
fprintf(stderr, "%s - unable to seek to start of file\n", p);
|
|
_close(fh);
|
|
return;
|
|
}
|
|
count = 0;
|
|
if (oldSize > MAXFILESIZE)
|
|
fprintf( stderr, "%s - file too large (%ld)\n", p, oldSize );
|
|
else
|
|
if (!myread( fh, oldSize )) {
|
|
if (oldSize != 0) {
|
|
fprintf( stderr, "%s - error while reading\n", p );
|
|
}
|
|
} else {
|
|
count = MungeFile( fRepeatMunge,
|
|
p,
|
|
InputFileBuf,
|
|
oldSize,
|
|
OutputFileBuf,
|
|
MAXFILESIZE,
|
|
(unsigned long *)&newSize
|
|
);
|
|
if (count == -1)
|
|
fprintf( stderr, "%s - output buffer overflow", p );
|
|
|
|
UnmapViewOfFile( InputFileBuf );
|
|
}
|
|
_close( fh );
|
|
|
|
if (count > 0) {
|
|
if (fRepeatMunge) {
|
|
fprintf( stderr, " - munge again" );
|
|
} else {
|
|
dwFileAttributes = GetFileAttributes( p );
|
|
fprintf( stderr, "%s", p );
|
|
}
|
|
|
|
if (!fQuery && _access( p, 2 ) == -1) {
|
|
if (!(fUseSLM || fUseAttrib)) {
|
|
fprintf( stderr, "%s - write protected, unable to apply changes\n", p );
|
|
return;
|
|
}
|
|
|
|
if (fRepeatMunge) {
|
|
fprintf( stderr, " - %s failed, %s still write-protected\n",
|
|
fUseSLM ? "OUT" : "ATTRIB", p );
|
|
printf( "%s(1) : UNABLE TO RUN %s command.\n", p, fUseSLM ? "OUT" : "ATTRIB" );
|
|
fflush( stdout );
|
|
return;
|
|
}
|
|
|
|
s = p + strlen( p );
|
|
while (s > p) {
|
|
if (*--s == '\\') {
|
|
*s++ = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (s != p) {
|
|
CurrentDirectory = PushCurrentDirectory( p );
|
|
} else {
|
|
CurrentDirectory = NULL;
|
|
}
|
|
|
|
if (fUseAttrib) {
|
|
fprintf( stderr, " - ATTRIB -r" );
|
|
if (SetFileAttributes( s,
|
|
dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY |
|
|
FILE_ATTRIBUTE_HIDDEN |
|
|
FILE_ATTRIBUTE_SYSTEM
|
|
)
|
|
)
|
|
) {
|
|
} else {
|
|
if (CurrentDirectory) {
|
|
s[-1] = '\\';
|
|
}
|
|
|
|
fprintf( stderr, " - failed (rc == %d), %s still write-protected\n",
|
|
GetLastError(), p );
|
|
printf( "%s(1) : UNABLE TO MAKE WRITABLE\n", p );
|
|
fflush( stdout );
|
|
return;
|
|
}
|
|
} else {
|
|
sprintf( CommandLine, "out %s%s", fForceSLM ? "-z " : "", s );
|
|
fprintf( stderr, " - check out" );
|
|
fflush( stdout );
|
|
fflush( stderr );
|
|
rc = system( CommandLine );
|
|
|
|
if (rc == -1) {
|
|
if (CurrentDirectory) {
|
|
s[-1] = '\\';
|
|
}
|
|
|
|
fprintf( stderr, " - OUT failed (rc == %d), %s still write-protected\n", errno, p );
|
|
printf( "%s(1) : UNABLE TO CHECK OUT\n", p );
|
|
fflush( stdout );
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
GetCurrentDirectory( sizeof( CommandLine ), CommandLine );
|
|
if (CurrentDirectory) {
|
|
PopCurrentDirectory( CurrentDirectory );
|
|
s[-1] = '\\';
|
|
}
|
|
|
|
if (fUseSLM && UndoScriptFile != NULL) {
|
|
if (!(UndoCurDirCount++ % 8)) {
|
|
if (UndoCurDirCount == 1) {
|
|
fprintf( UndoScriptFile, "\ncd %s", CommandLine );
|
|
}
|
|
|
|
fprintf( UndoScriptFile, "\nin -vi" );
|
|
}
|
|
|
|
fprintf( UndoScriptFile, " %s", s );
|
|
fflush( UndoScriptFile );
|
|
}
|
|
|
|
fRepeatMunge = TRUE;
|
|
goto RepeatMunge;
|
|
} else
|
|
if (!fQuery && _access( p, 2 ) != -1 && fUseSLM && !fRepeatMunge) {
|
|
if (!fSummary) {
|
|
printf( "%s(1) : FILE ALREADY CHECKED OUT\n", p );
|
|
fflush( stdout );
|
|
}
|
|
}
|
|
|
|
RememberMunge( p, count );
|
|
if (fQuery) {
|
|
fprintf( stderr, " [%d potential changes]\n", count );
|
|
} else {
|
|
if ( (fh = _creat( newName, S_IWRITE | S_IREAD )) == -1 )
|
|
fprintf( stderr, " - unable to create new version (%s)\n",
|
|
newName );
|
|
else
|
|
if (mywrite( fh, OutputFileBuf, newSize ) != newSize) {
|
|
fprintf( stderr, " - error while writing\n" );
|
|
_close( fh );
|
|
_unlink( newName );
|
|
} else {
|
|
_close( fh );
|
|
if (fTrustMe) {
|
|
_unlink( p );
|
|
} else {
|
|
if (_access( bakName, 0 ) == 0) {
|
|
_unlink( bakName );
|
|
}
|
|
|
|
if (rename( p, bakName )) {
|
|
fprintf( stderr, "MUNGE: rename %s to %s failed\n",
|
|
p, bakName );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (rename( newName, p )) {
|
|
fprintf( stderr, "MUNGE: rename %s to %s failed\n",
|
|
newName, p );
|
|
} else {
|
|
if (fRepeatMunge && fUseAttrib) {
|
|
SetFileAttributes( p, dwFileAttributes );
|
|
} else {
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
RememberMunge( p, count );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DoFiles(
|
|
char *p,
|
|
struct findType *b,
|
|
void *Args
|
|
)
|
|
{
|
|
int SaveCurDirCount;
|
|
char *s;
|
|
unsigned long i;
|
|
int FileProcessed;
|
|
|
|
if (strcmp ((const char *)b->fbuf.cFileName, ".") &&
|
|
strcmp ((const char *)b->fbuf.cFileName, "..") &&
|
|
strcmp ((const char *)b->fbuf.cFileName, "slm.dif")
|
|
) {
|
|
if (HASATTR(b->fbuf.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY)) {
|
|
switch (p[strlen(p)-1]) {
|
|
case '/':
|
|
case '\\': strcat (p, "*.*"); break;
|
|
default: strcat (p, "\\*.*");
|
|
}
|
|
|
|
if (fRecurse) {
|
|
fprintf( stderr, "Scanning %s\n", p );
|
|
SaveCurDirCount = UndoCurDirCount;
|
|
UndoCurDirCount = 0;
|
|
forfile( p,
|
|
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
|
|
DoFiles,
|
|
NULL
|
|
);
|
|
if (UndoScriptFile != NULL) {
|
|
if (UndoCurDirCount != 0) {
|
|
fprintf( UndoScriptFile, "\n" );
|
|
fflush( UndoScriptFile );
|
|
UndoCurDirCount = 0;
|
|
} else {
|
|
UndoCurDirCount = SaveCurDirCount;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
s = _strlwr( (char *)b->fbuf.cFileName );
|
|
while (*s != '.') {
|
|
if (*s == '\0') {
|
|
break;
|
|
} else {
|
|
s++;
|
|
}
|
|
}
|
|
|
|
FileProcessed = FALSE;
|
|
if (*s) {
|
|
if (!strcmp( s, "mge" ) || !strcmp( s, "bak" )) {
|
|
FileProcessed = TRUE;
|
|
} else {
|
|
for (i=0; i<NumberOfFileExtensions; i++) {
|
|
if (!strcmp( FileExtensions[ i ], s+1 )) {
|
|
FileProcessed = TRUE;
|
|
DoFile( p );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!FileProcessed) {
|
|
*s = '\0';
|
|
for (i=0; i<NumberOfFileNames; i++) {
|
|
if (!strcmp( FileNames[ i ], (const char *)b->fbuf.cFileName )) {
|
|
FileProcessed = TRUE;
|
|
DoFile( p );
|
|
break;
|
|
}
|
|
}
|
|
*s = '.';
|
|
}
|
|
} else {
|
|
for (i=0; i<NumberOfFileNames; i++) {
|
|
if (!strcmp( FileNames[ i ], (const char *)b->fbuf.cFileName )) {
|
|
FileProcessed = TRUE;
|
|
DoFile( p );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!FileProcessed) {
|
|
for (i=0; i<NumberOfFileNameAndExts; i++) {
|
|
if (!strcmp( FileNameAndExts[ i ], (const char *)b->fbuf.cFileName )) {
|
|
FileProcessed = TRUE;
|
|
DoFile( p );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Args;
|
|
}
|
|
|
|
void
|
|
Usage( char *MsgFmt, int MsgArg )
|
|
{
|
|
fputs("usage: munge scriptFile [-q [-e] [-o]] [-v] [-i] [-k] [-r] [-c [-m] [-z] [-@]]\n"
|
|
" [-n] [-l | -L] [-a | -s [-f]] [-u undoFileName]\n"
|
|
" filesToMunge...\n"
|
|
"Where...\n"
|
|
" -q\tQuery only - don't actually make changes.\n"
|
|
" -e\tQuery only - display entire line for each match\n"
|
|
" -o\tQuery only - just display filename once on first match\n"
|
|
" -v\tVerbose - show files being scanned\n"
|
|
" -i\tJust output summary of files changed at end\n"
|
|
" -k\tCase - Case sensitive scriptFile\n"
|
|
" -r\tRecurse.\n"
|
|
" -c\tIf no munge of file, then check for cleanlyness\n"
|
|
" -m\tCollapse multiple carriage returns into one\n"
|
|
" -z\tCtrl-Z will truncate file\n"
|
|
" -@\tRemove null characters\n"
|
|
" -n\tNeuter - Surround all strings with TEXT()\n"
|
|
" -l\tLiterals - process any quoted text (includes comments too)\n"
|
|
" -L\tLiterals - process any quoted text (excludes comments)\n"
|
|
" -s\tUse OUT command command for files that are readonly\n"
|
|
" -a\tUse ATTRIB -r command for files that are readonly\n"
|
|
" -f\tUse -z flag for SLM OUT command\n"
|
|
" -t\tTrust me and dont create .bak files\n"
|
|
" -u\tGenerate an undo script file for any SLM OUT commands invoked.\n"
|
|
" -?\tGets you this message\n\n"
|
|
"and scriptFile lines take any of the following forms:\n\n"
|
|
" oldName newName\n"
|
|
" \"oldString\" \"newString\"\n"
|
|
" -F .Ext Name. Name.Ext\n\n"
|
|
"Where...\n"
|
|
" oldName and newName following C Identifier rules\n"
|
|
" oldString and newString are arbitrary text strings\n"
|
|
" -F limits the munge to files that match:\n"
|
|
" a particular extension (.Ext)\n"
|
|
" a particular name (Name.)\n"
|
|
" a particular name and extension (Name.Ext)\n"
|
|
" If no -F line is seen in the scriptFile, then\n"
|
|
" the following is the default:\n"
|
|
" -F .asm .bat .c .cli .cpp .cxx .def .dlg .h .htm .hpj .hxx .idl .inc\n"
|
|
" -F .inf .lic .mak .mc .odl .rc .rcv .reg .s .src .srv .tk .w .x\n"
|
|
" -F makefil0 makefile sources\n",
|
|
stderr);
|
|
|
|
if (MsgFmt != NULL) {
|
|
fprintf( stderr, "\n" );
|
|
fprintf( stderr, MsgFmt, MsgArg );
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
exit( 1 );
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
int i;
|
|
char *s, pathBuf[ 64 ];
|
|
int FileArgsSeen = 0;
|
|
|
|
ConvertAppToOem( argc, argv );
|
|
if (argc < 3) {
|
|
Usage( NULL, 0 );
|
|
}
|
|
|
|
if ( !InitTokenMappingTable()) {
|
|
fprintf( stderr, "MUNGE: Unable to create symbol table\n" );
|
|
exit( 1 );
|
|
}
|
|
|
|
OutputFileBuf = (char *)VirtualAlloc( NULL,
|
|
MAXFILESIZE,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
);
|
|
if ( OutputFileBuf == NULL) {
|
|
fprintf( stderr, "not enough memory\n" );
|
|
exit( 1 );
|
|
}
|
|
|
|
fClean = FALSE;
|
|
fRemoveDuplicateCR = FALSE;
|
|
fRemoveImbeddedNulls = FALSE;
|
|
fTruncateWithCtrlZ = FALSE;
|
|
fQuery = FALSE;
|
|
fFileOnly = FALSE;
|
|
fRecurse = FALSE;
|
|
fUseAttrib = FALSE;
|
|
fUseSLM = FALSE;
|
|
fForceSLM = FALSE;
|
|
fTrustMe = FALSE;
|
|
fVerbose = FALSE;
|
|
UndoScriptFileName = NULL;
|
|
UndoScriptFile = NULL;
|
|
fSummary = FALSE;
|
|
fInsideQuotes = FALSE;
|
|
fInsideComments = FALSE;
|
|
fNeuter = FALSE;
|
|
fEntireLine = FALSE;
|
|
|
|
for (i=2; i<argc; i++) {
|
|
s = argv[ i ];
|
|
if (*s == '-' || *s == '/') {
|
|
while (*++s) {
|
|
switch ( tolower( *s ) ) {
|
|
case 'm': fRemoveDuplicateCR = TRUE; break;
|
|
case '@': fRemoveImbeddedNulls = TRUE; break;
|
|
case 'z': fTruncateWithCtrlZ = TRUE; break;
|
|
case 'c': fClean = TRUE; break;
|
|
case 'q': fQuery = TRUE; break;
|
|
case 'o': fFileOnly = TRUE; break;
|
|
case 'r': fRecurse = TRUE; break;
|
|
case 'a': fUseAttrib = TRUE; break;
|
|
case 's': fUseSLM = TRUE; break;
|
|
case 'f': fForceSLM = TRUE; break;
|
|
case 't': fTrustMe = TRUE; break;
|
|
case 'v': fVerbose = TRUE; break;
|
|
case 'i': fSummary = TRUE; break;
|
|
case 'l': if (*s != 'L') fInsideComments = TRUE;
|
|
fInsideQuotes = TRUE; break;
|
|
case 'n': fNeuter = TRUE; fInsideQuotes = FALSE; break;
|
|
case 'k': fCaseSensitive = TRUE; break;
|
|
case 'e': fEntireLine = TRUE; break;
|
|
case 'u': UndoScriptFileName = argv[ ++i ];
|
|
break;
|
|
|
|
default: Usage( "invalid switch - '%c'", *s );
|
|
}
|
|
}
|
|
} else {
|
|
if ((fFileOnly | fEntireLine) && !fQuery) {
|
|
Usage( "-e or -o invalid without -q", 0 );
|
|
}
|
|
|
|
if (fQuery && (fClean ||
|
|
fRemoveDuplicateCR ||
|
|
fRemoveImbeddedNulls ||
|
|
fTruncateWithCtrlZ ||
|
|
fUseSLM ||
|
|
fForceSLM ||
|
|
fTrustMe ||
|
|
UndoScriptFile ||
|
|
fNeuter
|
|
)
|
|
) {
|
|
Usage( "-q valid only with -e or -o", 0 );
|
|
}
|
|
|
|
if (fClean &&
|
|
!fRemoveDuplicateCR &&
|
|
!fRemoveImbeddedNulls &&
|
|
!fTruncateWithCtrlZ
|
|
) {
|
|
Usage( "-c requires at least one of -m, -z or -@", 0 );
|
|
}
|
|
|
|
if (UndoScriptFileName != NULL) {
|
|
if (!fUseSLM) {
|
|
Usage ("-u invalid with -s", 0 );
|
|
} else {
|
|
UndoScriptFile = fopen( UndoScriptFileName, "w" );
|
|
if (UndoScriptFile == NULL) {
|
|
fprintf( stderr, "Unable to open %s\n", UndoScriptFileName );
|
|
exit( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!FileArgsSeen++) {
|
|
if (!ReadScriptFile( argv[ 1 ] )) {
|
|
fprintf( stderr, "Invalid script file - %s\n", argv[ 1 ] );
|
|
exit( 1 );
|
|
}
|
|
|
|
if (fVerbose) {
|
|
DisplayFilePatterns();
|
|
}
|
|
}
|
|
|
|
if (GetFileAttributes( s ) & FILE_ATTRIBUTE_DIRECTORY) {
|
|
s = strcpy( pathBuf, s );
|
|
switch (s[strlen(s)-1]) {
|
|
case '/':
|
|
case '\\': strcat (s, "*.*"); break;
|
|
default: strcat (s, "\\*.*");
|
|
}
|
|
fprintf( stderr, "Scanning %s\n", s );
|
|
UndoCurDirCount = 0;
|
|
forfile( s,
|
|
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
|
|
DoFiles,
|
|
NULL
|
|
);
|
|
} else {
|
|
UndoCurDirCount = 0;
|
|
DoFile( s );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FileArgsSeen == 0) {
|
|
if (!ReadScriptFile( argv[ 1 ] )) {
|
|
fprintf( stderr, "Invalid script file - %s\n", argv[ 1 ] );
|
|
exit( 1 );
|
|
}
|
|
|
|
if (fVerbose) {
|
|
DisplayFilePatterns();
|
|
}
|
|
|
|
s = "*.*";
|
|
fprintf( stderr, "Scanning %s\n", s );
|
|
UndoCurDirCount = 0;
|
|
forfile( s,
|
|
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
|
|
DoFiles,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (UndoScriptFile != NULL) {
|
|
if (UndoCurDirCount != 0) {
|
|
fprintf( UndoScriptFile, "\n" );
|
|
}
|
|
|
|
fclose( UndoScriptFile );
|
|
}
|
|
|
|
DumpMungedList();
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
DisplayFilePatterns( void )
|
|
{
|
|
unsigned long i;
|
|
|
|
if (NumberOfFileExtensions) {
|
|
fprintf( stderr, "Munge will look at files with the following extensions:\n " );
|
|
for (i=0; i<NumberOfFileExtensions; i++) {
|
|
fprintf( stderr, " %s", FileExtensions[ i ] );
|
|
}
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
|
|
if (NumberOfFileNames) {
|
|
fprintf( stderr, "Munge will look at files with the following names:\n " );
|
|
for (i=0; i<NumberOfFileNames; i++) {
|
|
fprintf( stderr, " %s", FileNames[ i ] );
|
|
}
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
|
|
if (NumberOfFileNameAndExts) {
|
|
fprintf( stderr, "Munge will look at files with the following name and extensions:\n " );
|
|
for (i=0; i<NumberOfFileNameAndExts; i++) {
|
|
fprintf( stderr, " %s", FileNameAndExts[ i ] );
|
|
}
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
}
|
|
|
|
|
|
char *
|
|
PushCurrentDirectory(
|
|
char *NewCurrentDirectory
|
|
)
|
|
{
|
|
char *OldCurrentDirectory;
|
|
|
|
if (OldCurrentDirectory = malloc( MAX_PATH )) {
|
|
GetCurrentDirectory( MAX_PATH, OldCurrentDirectory );
|
|
SetCurrentDirectory( NewCurrentDirectory );
|
|
} else {
|
|
fprintf( stderr,
|
|
"MUNGE: (Fatal Error) PushCurrentDirectory out of memory\n"
|
|
);
|
|
exit( 16 );
|
|
}
|
|
|
|
return( OldCurrentDirectory );
|
|
}
|
|
|
|
|
|
void
|
|
PopCurrentDirectory(
|
|
char *OldCurrentDirectory
|
|
)
|
|
{
|
|
if (OldCurrentDirectory) {
|
|
SetCurrentDirectory( OldCurrentDirectory );
|
|
free( OldCurrentDirectory );
|
|
}
|
|
}
|
|
|
|
|
|
PVOID SymbolTableHandle;
|
|
|
|
|
|
BOOL
|
|
InitTokenMappingTable( void )
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = CreateSymbolTable( 257, 0x20000, &SymbolTableHandle );
|
|
if (NT_SUCCESS( Status )) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
SaveTokenMapping(
|
|
char *String,
|
|
char *Value
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING SymbolName;
|
|
ULONG_PTR SymbolValue;
|
|
|
|
RtlInitString( &AnsiString, String );
|
|
Status = RtlAnsiStringToUnicodeString( &SymbolName, &AnsiString, TRUE );
|
|
if (!NT_SUCCESS( Status )) {
|
|
return FALSE;
|
|
}
|
|
|
|
SymbolValue = (ULONG_PTR)Value;
|
|
Status = AddSymbolToSymbolTable( SymbolTableHandle,
|
|
&SymbolName,
|
|
&SymbolValue
|
|
);
|
|
RtlFreeUnicodeString( &SymbolName );
|
|
if (NT_SUCCESS( Status )) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
char *
|
|
FindTokenMapping(
|
|
char *String
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING SymbolName;
|
|
ULONG_PTR SymbolValue;
|
|
|
|
RtlInitString( &AnsiString, String );
|
|
Status = RtlAnsiStringToUnicodeString( &SymbolName, &AnsiString, TRUE );
|
|
if (!NT_SUCCESS( Status )) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = LookupSymbolInSymbolTable( SymbolTableHandle,
|
|
&SymbolName,
|
|
&SymbolValue
|
|
);
|
|
RtlFreeUnicodeString( &SymbolName );
|
|
if (NT_SUCCESS( Status )) {
|
|
return (char *)SymbolValue;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct _SYMBOL_TABLE_ENTRY {
|
|
struct _SYMBOL_TABLE_ENTRY *HashLink;
|
|
ULONG_PTR Value;
|
|
UNICODE_STRING Name;
|
|
} SYMBOL_TABLE_ENTRY, *PSYMBOL_TABLE_ENTRY;
|
|
|
|
typedef struct _SYMBOL_TABLE {
|
|
ULONG NumberOfBuckets;
|
|
PSYMBOL_TABLE_ENTRY Buckets[1];
|
|
} SYMBOL_TABLE, *PSYMBOL_TABLE;
|
|
|
|
NTSTATUS
|
|
CreateSymbolTable(
|
|
IN ULONG NumberOfBuckets,
|
|
IN ULONG MaxSymbolTableSize,
|
|
OUT PVOID *SymbolTableHandle
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PSYMBOL_TABLE p;
|
|
ULONG Size;
|
|
|
|
RtlLockHeap( GetProcessHeap() );
|
|
|
|
if (*SymbolTableHandle == NULL) {
|
|
Size = sizeof( SYMBOL_TABLE ) +
|
|
(sizeof( SYMBOL_TABLE_ENTRY ) * (NumberOfBuckets-1));
|
|
|
|
p = (PSYMBOL_TABLE)RtlAllocateHeap( GetProcessHeap(), 0, Size );
|
|
if (p == NULL) {
|
|
Status = STATUS_NO_MEMORY;
|
|
} else {
|
|
RtlZeroMemory( p, Size );
|
|
p->NumberOfBuckets = NumberOfBuckets;
|
|
*SymbolTableHandle = p;
|
|
}
|
|
}
|
|
|
|
RtlUnlockHeap( GetProcessHeap() );
|
|
|
|
return( Status );
|
|
}
|
|
|
|
|
|
PSYMBOL_TABLE_ENTRY
|
|
BasepHashStringToSymbol(
|
|
IN PSYMBOL_TABLE p,
|
|
IN PUNICODE_STRING Name,
|
|
OUT PSYMBOL_TABLE_ENTRY **PreviousSymbol
|
|
)
|
|
{
|
|
ULONG n, Hash;
|
|
WCHAR c;
|
|
PWCH s;
|
|
PSYMBOL_TABLE_ENTRY *pps, ps;
|
|
|
|
n = Name->Length / sizeof( c );
|
|
s = Name->Buffer;
|
|
if ( fCaseSensitive ) {
|
|
Hash = 0;
|
|
while (n--) {
|
|
c = *s++;
|
|
Hash = Hash + (c << 1) + (c >> 1) + c;
|
|
}
|
|
} else {
|
|
Hash = 0;
|
|
while (n--) {
|
|
c = RtlUpcaseUnicodeChar( *s++ );
|
|
Hash = Hash + (c << 1) + (c >> 1) + c;
|
|
}
|
|
}
|
|
|
|
pps = &p->Buckets[ Hash % p->NumberOfBuckets ];
|
|
while (ps = *pps) {
|
|
if (RtlEqualUnicodeString( &ps->Name, Name, (BOOLEAN)!fCaseSensitive )) {
|
|
break;
|
|
} else {
|
|
pps = &ps->HashLink;
|
|
}
|
|
}
|
|
|
|
*PreviousSymbol = pps;
|
|
return( ps );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AddSymbolToSymbolTable(
|
|
IN PVOID SymbolTableHandle,
|
|
IN PUNICODE_STRING SymbolName,
|
|
IN ULONG_PTR * SymbolValue OPTIONAL
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PSYMBOL_TABLE p = (PSYMBOL_TABLE)SymbolTableHandle;
|
|
PSYMBOL_TABLE_ENTRY ps, *pps;
|
|
ULONG_PTR Value;
|
|
|
|
if (ARGUMENT_PRESENT( SymbolValue )) {
|
|
Value = *SymbolValue;
|
|
} else {
|
|
Value = 0;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
RtlLockHeap( GetProcessHeap() );
|
|
try {
|
|
ps = BasepHashStringToSymbol( p, SymbolName, &pps );
|
|
if (ps == NULL) {
|
|
ps = RtlAllocateHeap( GetProcessHeap(), 0, (sizeof( *ps ) + SymbolName->Length) );
|
|
if (ps != NULL) {
|
|
ps->HashLink = NULL;
|
|
ps->Value = Value;
|
|
ps->Name.Buffer = (PWSTR)(ps + 1);
|
|
ps->Name.Length = SymbolName->Length;
|
|
ps->Name.MaximumLength = (USHORT)(SymbolName->Length + sizeof( UNICODE_NULL ));
|
|
RtlMoveMemory( ps->Name.Buffer, SymbolName->Buffer, SymbolName->Length );
|
|
*pps = ps;
|
|
} else {
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
else {
|
|
Status = STATUS_OBJECT_NAME_EXISTS;
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
RtlUnlockHeap( GetProcessHeap() );
|
|
|
|
return( Status );
|
|
}
|
|
|
|
NTSTATUS
|
|
LookupSymbolInSymbolTable(
|
|
IN PVOID SymbolTableHandle,
|
|
IN PUNICODE_STRING SymbolName,
|
|
OUT ULONG_PTR *SymbolValue OPTIONAL
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PSYMBOL_TABLE p = (PSYMBOL_TABLE)SymbolTableHandle;
|
|
PSYMBOL_TABLE_ENTRY ps, *pps;
|
|
ULONG_PTR Value;
|
|
|
|
RtlLockHeap( GetProcessHeap() );
|
|
try {
|
|
ps = BasepHashStringToSymbol( p, SymbolName, &pps );
|
|
if (ps == NULL) {
|
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
Value = 0;
|
|
} else {
|
|
Status = STATUS_SUCCESS;
|
|
Value = ps->Value;
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
RtlUnlockHeap( GetProcessHeap() );
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
if (ARGUMENT_PRESENT( SymbolValue )) {
|
|
*SymbolValue = Value;
|
|
}
|
|
}
|
|
|
|
return( Status );
|
|
}
|