Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1230 lines
29 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1990-1992 **/
/**********************************************************************/
/*
uixport.c
This program parses the output of the "COFF -DUMP -SYMBOLS" command
and extract all public symbols. This is used to generate .DEF files
for DLLs.
FILE HISTORY:
KeithMo 09-Aug-1992 00.00.00 Created.
KeithMo 14-Sep-1992 00.00.01 Strip stdcall decoration from symbols.
KeithMo 16-Oct-1992 00.00.02 Handle goofy []()* in coff output.
DavidHov 18-Sep-1993 00.00.04 Added exclusion list processing.
The exlusion list is generated
mechanically and constiutes all the
symbols which are not imported
by any known NETUI/RAS/MAC (et al.)
binary.
DavidHov 22-Sep-1993 00.00.05 Added symbol ignore table and logic.
The ignore table at this time ignores
only the gigantic symbols generated
by C8 when /Gf is used; these names
are strings which are to be merged
at link time.
DaveWolfe 06-Jul-1994 00.01.01 (Motorola) Added -ppc option for
PowerPC to strip entry point symbols
generated for PPC TOC.
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>
//
// This is the maximum length (in characters) of any line we'll
// receive from COFF. If we receive a longer line, the program
// won't crash, but we may miss a public symbol.
//
#define MAX_LINE_FROM_COFF 2000
//
// This is the maximum length (in characters) of any symbol we'll
// receive from COFF.
//
#define MAX_SYMBOL 247
//
// This is the maximum length (in characters) of any error message
// we'll display.
//
#define MAX_ERROR_MESSAGE 256
//
// This is the length (in characters) of the header->output copy buffer.
//
#define HEADER_COPY_BUFFER_SIZE 256
//
// Messages.
//
char _szBanner[] = "%s version 00.01.01\n";
char _szCannotOpenForRead[] = "Cannot open %s for read access.";
char _szCannotOpenForWrite[] = "Cannot open %s for write access.";
char _szErrorCopyingHeader[] = "Error copying header to output.";
char _szInvalidSwitch[] = "Invalid switch '%c'.\n\n";
char _szSymbolTooLong[] = "Symbol %s exceeds max symbol length!\n";
char _szExclusionError[] = "Error processing exclusion list file; ignored" ;
char _szExclusionEmpty[] = "Exclusion list file specified is empty; ignored" ;
//
// Globals.
//
char * _pszProgramName;
FILE * _fileIn;
FILE * _fileOut;
FILE * _fileHeader;
int _fStripLeadingUnderscore;
int _fNukeStdcallDecoration;
int _fPowerPC;
int _fIA64;
char * _pszExclusionListFile = NULL ;
void * _pvExclusionBlock = NULL ;
char * * _apszExclusionArray = NULL ;
int _cExclusionItems = -1 ;
int _cExcludedItems = 0 ;
int _cIgnoredItems = 0 ;
// This table contains the prefixes of symbol names to ignore
// while building the DEF file. See ValidSymbol().
static char * apszIgnore [] =
{
"??_C@_", // Ignore generated string symbol names
NULL
};
//
// Prototypes.
//
int __cdecl main( int cArgs,
char * pArgs[] );
void Cleanup( void );
void CopyHeaderToOutput( FILE * fHeader,
FILE * fOutput );
int ExtractSymbol( char * pszLineFromCoff,
char * pszSymbol );
void __cdecl FatalError( int err,
char * pszFmt,
... );
void __cdecl NonFatalError( char * pszFmt,
... );
int IsHexNumber( char * pszHexNumber );
char * NoPath( char * pszPathName );
void ProcessCommandLine( int cArgs,
char * pArgs[] );
void StripStdcallDecoration( char * pszSymbol );
void Usage( void );
// Create the exclusion list.
int CreateExclusionList ( char * pszFileName,
void * * pvData,
char * * * apszStrings ) ;
// Check the excluded symbol list for this name
int ExcludedSymbol ( char * pszSymbol ) ;
int ValidSymbol ( const char * psz ) ;
/*******************************************************************
NAME: main
SYNOPSIS: C program entrypoint.
ENTRY: cArgs - Number of command line arguments.
pArgs - An array of pointers to the
command line arguments.
RETURNS: int - 0 if everything ran OK,
!0 if an error occurred.
NOTES: See the Usage() function for valid command line arguments.
HISTORY:
KeithMo 09-Aug-1992 Created.
KeithMo 14-Sep-1992 Strip stdcall decoration from symbols.
********************************************************************/
int __cdecl main( int cArgs,
char * pArgs[] )
{
//
// A line read from COFF.
//
char szLineFromCoff[MAX_LINE_FROM_COFF+1];
//
// A symbol extracted from the COFF line.
//
char szSymbol[MAX_SYMBOL+1];
//
// Get the program name, for our messages.
//
_pszProgramName = NoPath( pArgs[0] );
//
// Announce ourselves.
//
fprintf( stderr,
_szBanner,
_pszProgramName );
//
// Parse the command line arguments.
//
ProcessCommandLine( cArgs, pArgs );
//
// If requested, copy the header file before processing
// the COFF output.
//
if( _fileHeader != NULL )
{
CopyHeaderToOutput( _fileHeader, _fileOut );
}
//
// If an exclusion list file was specified, process it.
// If it's empty, ignore it.
//
if ( _pszExclusionListFile )
{
_cExclusionItems = CreateExclusionList( _pszExclusionListFile,
& _pvExclusionBlock,
& _apszExclusionArray ) ;
if ( _cExclusionItems < 0 )
{
_pszExclusionListFile = NULL ;
NonFatalError( _szExclusionError ) ;
}
else
if ( _cExclusionItems == 0 )
{
_pszExclusionListFile = NULL ;
NonFatalError( _szExclusionEmpty ) ;
}
}
//
// Read the lines from coff, extract the symbols, and
// write them to the output file.
//
while( fgets( szLineFromCoff, MAX_LINE_FROM_COFF, _fileIn ) != NULL )
{
char * pszDisplay = szSymbol;
if( !ExtractSymbol( szLineFromCoff, szSymbol ) )
{
continue;
}
if ( ! _fNukeStdcallDecoration )
{
StripStdcallDecoration( szSymbol );
}
if ( ! ValidSymbol( pszDisplay ) )
{
_cIgnoredItems++ ;
continue ;
}
if ( _pszExclusionListFile && ExcludedSymbol( szSymbol ) )
{
_cExcludedItems++ ;
continue ;
}
if( _fStripLeadingUnderscore && ( *pszDisplay == '_' ) )
{
pszDisplay++;
}
fprintf( _fileOut, "%s\n", pszDisplay );
}
fprintf( _fileOut, "\032" );
// Give a synopsis of exclusion file processesing.
fprintf( stdout, "\nSymbols ignored: %ld\n", _cIgnoredItems ) ;
if ( _pszExclusionListFile )
{
fprintf( stdout, "\nExcluded symbols registered: %ld, excluded: %ld\n",
_cExclusionItems, _cExcludedItems ) ;
}
//
// Cleanup any open files, then exit.
//
Cleanup();
return 0;
} // main
/*******************************************************************
NAME: Cleanup
SYNOPSIS: Cleanup the app just before termination. Closes any
open files, frees memory buffers, etc.
HISTORY:
KeithMo 09-Aug-1992 Created.
********************************************************************/
void Cleanup( void )
{
if( _fileHeader != NULL )
{
fclose( _fileHeader );
}
if( _fileIn != stdin )
{
fclose( _fileIn );
}
if( _fileOut != stdout )
{
fclose( _fileOut );
}
if ( _pvExclusionBlock )
{
free( _pvExclusionBlock ) ;
}
if ( _apszExclusionArray )
{
free( _apszExclusionArray ) ;
}
} // Cleanup
/*******************************************************************
NAME: CopyHeaderToOutput
SYNOPSIS: Copies the specified header file to the output file.
ENTRY: fHeader - An open file stream (read access)
to the header file.
fOutput - An open file stream (write access)
to the output file.
NOTES: If any errors occur, FatalError() is called to terminate
the app.
HISTORY:
KeithMo 09-Aug-1992 Created.
********************************************************************/
void CopyHeaderToOutput( FILE * fHeader,
FILE * fOutput )
{
char achBuffer[HEADER_COPY_BUFFER_SIZE];
size_t cbRead;
while( ( cbRead = fread( achBuffer,
sizeof(char),
HEADER_COPY_BUFFER_SIZE,
fHeader ) ) != 0 )
{
if( fwrite( achBuffer,
sizeof(char),
cbRead,
fOutput ) < cbRead )
{
break;
}
}
if( ferror( fHeader ) || ferror( fOutput ) )
{
FatalError( 2, _szErrorCopyingHeader );
}
} // CopyHeaderToOutput
/*******************************************************************
NAME: ExtractSymbol
SYNOPSIS: Extracts a public symbol from a COFF output line.
ENTRY: pszLineFromCoff - A text line output from the
"COFF -DUMP -SYM" command.
Note: The text in the line
will be modified by the strtok()
function!
pszSymbol - Will receive the extracted symbol,
if one is found.
RETURNS: int - !0 if a symbol was extracted,
0 otherwise.
NOTES: Here's an example of the input (output from LINK32).
The symbol -$- indicates places where I broke the line
for clarity. This just one line:
009 00000000 SECT2 notype () External | -$-
??0APPLICATION@@IAE@PAUHINSTANCE__@@HIIII@Z -$-
(protected: __thiscall APPLICATION::APPLICATION( -$-
struct HINSTANCE__ *,int,unsigned int,unsigned int,-$-
unsigned int,unsigned int))
We choose only symbols which are part of a SECT and are
marked as "notype" and "External"
HISTORY:
KeithMo 09-Aug-1992 Created.
DavidHov 20-Oct-1993 update to new LINK32 output form.
********************************************************************/
int ExtractSymbol( char * pszLineFromCoff,
char * pszSymbol )
{
char * pszDelimiters = " \t\n";
char * pszSect = "SECT";
char * pszNoType = "notype";
char * pszExternal = "External";
char * pszToken;
char * pszPotentialSymbol;
char * pszScan;
//
// Verify that the first token is a hex number.
//
pszToken = strtok( pszLineFromCoff, pszDelimiters );
if( ( pszToken == NULL ) || !IsHexNumber( pszToken ) )
{
return 0;
}
//
// Verify that the second token is a hex number.
//
pszToken = strtok( NULL, pszDelimiters );
if( ( pszToken == NULL ) || !IsHexNumber( pszToken ) )
{
return 0;
}
//
// The third token must be SECTn (where n is one
// or more hex digits).
//
pszToken = strtok( NULL, pszDelimiters );
if( pszToken == NULL )
{
return 0;
}
if( ( _strnicmp( pszToken, pszSect, 4 ) )
|| ! IsHexNumber( pszToken + 4 ) )
{
return 0 ;
}
//
// Next, we have to have "notype"
//
pszToken = strtok( NULL, pszDelimiters );
if( pszToken == NULL ||
_stricmp( pszToken, pszNoType ) )
{
return 0;
}
//
// Functions have a () next, data exports don't.
//
pszToken = strtok( NULL, pszDelimiters );
if( pszToken == NULL )
{
return 0;
}
if ( strcmp( pszToken, "()" ) != 0 )
{
return 0;
}
//
// Next, we need "External"
//
pszToken = strtok( NULL, pszDelimiters );
if( pszToken == NULL )
{
return 0;
}
if( pszToken == NULL ||
_stricmp( pszToken, pszExternal ) )
{
return 0;
}
//
// Now, the symbol introducer: "|"
//
pszToken = strtok( NULL, pszDelimiters );
if( pszToken == NULL ||
_stricmp( pszToken, "|" ) )
{
return 0;
}
//
// Finally, the mangled (decorated) symbol itself.
//
pszPotentialSymbol = strtok( NULL, pszDelimiters );
if( pszPotentialSymbol == NULL )
{
return 0;
}
//
// Strip prefix from PowerPC function symbols
//
if( _fPowerPC )
{
pszPotentialSymbol += 2 ;
}
//
// Strip prefix from IA-64 function symbols
//
if( _fIA64 )
{
pszPotentialSymbol += 1 ;
}
if( strlen( pszPotentialSymbol ) > MAX_SYMBOL )
{
fprintf( stderr,
_szSymbolTooLong,
pszPotentialSymbol );
return 0;
}
//
// Got one.
//
strcpy( pszSymbol, pszPotentialSymbol );
return 1;
} // ExtractSymbol
/*******************************************************************
NAME: FatalError and NonFatalError
SYNOPSIS: Prints an error message to stderr, then terminates
the application.
ENTRY: err - An error code for the exit()
stdlib function.
pszFmt - A format string for vsprintf().
... - Any other arguments required
by the format string.
HISTORY:
KeithMo 09-Aug-1992 Created.
********************************************************************/
void __cdecl NonFatalError (
char * pszFmt,
... )
{
char szBuffer[MAX_ERROR_MESSAGE+1];
va_list ArgPtr;
va_start( ArgPtr, pszFmt );
fprintf( stderr, "%s => ", _pszProgramName );
vsprintf( szBuffer, pszFmt, ArgPtr );
fprintf( stderr, "%s\n", szBuffer );
va_end( ArgPtr );
} // NonFatalError
void __cdecl FatalError( int err,
char * pszFmt,
... )
{
char szBuffer[MAX_ERROR_MESSAGE+1];
va_list ArgPtr;
va_start( ArgPtr, pszFmt );
fprintf( stderr, "%s => ", _pszProgramName );
vsprintf( szBuffer, pszFmt, ArgPtr );
fprintf( stderr, "%s\n", szBuffer );
va_end( ArgPtr );
Cleanup();
exit( err );
} // FatalError
/*******************************************************************
NAME: IsHexNumber
SYNOPSIS: Determines if the specified string contains a hexadecimal
number.
ENTRY: pszHexNumber - The hex number.
EXIT: int - !0 if it *is* a hex number,
0 if it isn't.
HISTORY:
KeithMo 12-Aug-1992 Created.
********************************************************************/
int IsHexNumber( char * pszHexNumber )
{
int fResult = 1;
char ch;
while( ch = *pszHexNumber++ )
{
if( !isxdigit( ch ) )
{
fResult = 0;
break;
}
}
return fResult;
} // IsHexNumber
/*******************************************************************
NAME: NoPath
SYNOPSIS: Extracts the filename portion of a path.
ENTRY: pszPathName - Contains a path name. The name
is not necessarily canonicalized,
and may contain just a filename
component.
EXIT: char * - The filename component.
HISTORY:
KeithMo 09-Aug-1992 Created.
********************************************************************/
char * NoPath( char * pszPathName )
{
char * pszTmp;
char ch;
pszTmp = pszPathName;
while( ( ch = *pszPathName++ ) != '\0' )
{
if( ( ch == '\\' ) || ( ch == ':' ) )
{
pszTmp = pszPathName;
}
}
return pszTmp;
} // NoPath
/*******************************************************************
NAME: ProcessCommandLine
SYNOPSIS: Parse command line arguments, setting appropriate globals.
ENTRY: cArgs - Number of command line arguments.
pArgs - An array of pointers to the
command line arguments.
NOTES: See the Usage() function for valid command line arguments.
HISTORY:
KeithMo 12-Aug-1992 Broke out of main().
DaveWolfe 06-Jul-1994 Added -ppc.
********************************************************************/
void ProcessCommandLine( int cArgs,
char * pArgs[] )
{
int i;
char chSwitch;
//
// Setup our defaults.
//
_fileIn = stdin;
_fileOut = stdout;
_fileHeader = NULL;
_fStripLeadingUnderscore = 0;
_fNukeStdcallDecoration = 0;
_fPowerPC = 0;
_fIA64 = 0;
//
// Parse the command line arguments.
//
for( i = 1 ; i < cArgs ; i++ )
{
//
// Get the argument.
//
char * pszArg = pArgs[i];
char * pszParam;
//
// All of our valid arguments *must* start
// with a switch character. Enforce this.
//
if( ( *pszArg != '-' ) && ( *pszArg != '/' ) )
{
Usage();
}
chSwitch = *++pszArg;
//
// pszParam will either be NULL (for switches such
// as -s) or point to the text just past the colon
// (for switches such as -i:file).
//
if( ( pszArg[1] == ':' ) && ( pszArg[2] != '\0' ) )
{
pszParam = pszArg + 2;
}
else
{
pszParam = NULL;
}
//
// Check for valid arguments.
//
switch( chSwitch )
{
case 'p' :
case 'P' :
//
// -ppc
//
// Strip prefix ".." from "..symbol".
//
if( _stricmp( pszArg, "ppc") != 0 )
{
Usage();
}
_fPowerPC = 1;
break;
case 'h' :
case 'H' :
//
// -h:header_file
//
// If a header file has already been specified, or
// if there is no parameter after the switch, bag-out.
//
if( ( _fileHeader != NULL ) || ( pszParam == NULL ) )
{
Usage();
}
_fileHeader = fopen( pszParam, "r" );
if( _fileHeader == NULL )
{
FatalError( 1, _szCannotOpenForRead, pszParam );
}
break;
case 'i' :
case 'I' :
if (pszParam == NULL) {
//
// -ia64
//
// Strip prefix "." from ".symbol".
//
if( _stricmp( pszArg, "ia64") != 0 )
{
Usage();
}
_fIA64 = 1;
} else {
//
// -i:input_file
//
// If an input file has already been specified, or
// if there is no parameter after the switch, bag-out.
//
if( ( _fileIn != stdin ) || ( pszParam == NULL ) )
{
Usage();
}
_fileIn = fopen( pszParam, "r" );
if( _fileIn == NULL )
{
FatalError( 1, _szCannotOpenForRead, pszParam );
}
}
break;
case 'o' :
case 'O' :
//
// -o:output_file
//
// If an output file has already been specified, or
// if there is no parameter after the switch, bag-out.
//
if( ( _fileOut != stdout ) || ( pszParam == NULL ) )
{
Usage();
}
_fileOut = fopen( pszParam, "w" );
if( _fileOut == NULL )
{
FatalError( 1, _szCannotOpenForWrite, pszParam );
}
break;
case 's' :
case 'S' :
//
// -s
//
// If this switch has already been specified, bag-out.
//
if( _fStripLeadingUnderscore )
{
Usage();
}
_fStripLeadingUnderscore = 1;
break;
case 'n' :
case 'N' :
_fNukeStdcallDecoration = 1 ;
break ;
case 'x' :
case 'X' :
_pszExclusionListFile = pszParam ;
break ;
case '?' :
//
// -?
//
// Give the poor user a clue.
//
Usage();
break;
default :
//
// Invalid switch.
//
// Tell the user the bad news, then bag-out.
//
fprintf( stderr, _szInvalidSwitch, chSwitch );
Usage();
break;
}
}
} // ProcessCommandLine
/*******************************************************************
NAME: StripStdcallDecoration
SYNOPSIS: Stdcall builds use a weak form of type-safe linkage.
This is implemented by appending "@nn" to the end
of each symbol, where "nn" is the number of *bytes*
passed as parameters.
COFF, on the other hand, does *not* want to see
this symbol decoration in .DEF files. So, we remove
it here.
ENTRY: pszSymbol - The symbol to munge.
NOTES: This routine is *NOT* DBCS safe! Do we care?
HISTORY:
KeithMo 14-Sep-1992 Created.
********************************************************************/
void StripStdcallDecoration( char * pszSymbol )
{
int count = 0 ;
//
// Find the last character.
//
pszSymbol += strlen( pszSymbol ) - 1;
//
// Skip any *decimal* numbers.
//
while( isdigit( *pszSymbol ) )
{
pszSymbol--;
count++ ;
}
//
// If we're now pointing at a "@", terminate the string here.
//
if( count && *pszSymbol == '@' )
{
*pszSymbol = '\0';
}
} // StripStdcallDecoration
/*******************************************************************
NAME: Usage
SYNOPSIS: Displays usage information if the user gives us a
bogus command line.
HISTORY:
KeithMo 09-Aug-1992 Created.
DaveWolfe 06-Jul-1994 Added -ppc option.
********************************************************************/
void Usage( void )
{
fprintf( stderr, "use: %s [options]\n", _pszProgramName );
fprintf( stderr, "\n" );
fprintf( stderr, "Valid options are:\n" );
fprintf( stderr, " -i:input_file = source file\n" );
fprintf( stderr, " -o:output_file = destination file\n" );
fprintf( stderr, " -h:header_file = header to prepend before symbols\n" );
fprintf( stderr, " -s = strip first leading underscore from symbols\n" );
fprintf( stderr, " -n = do not strip __stdcall decoration @nn\n" );
fprintf( stderr, " -x:excl_file = name of file containing excluded symbols\n" );
fprintf( stderr, " -ppc = input is PowerPC symbol dump\n" );
fprintf( stderr, " -ia64 = input is IA-64 symbol dump\n" );
fprintf( stderr, " -? = show this help\n" );
fprintf( stderr, "\n" );
fprintf( stderr, "Defaults are:\n" );
fprintf( stderr, " input_file = stdin\n" );
fprintf( stderr, " output_file = stdout\n" );
fprintf( stderr, " header_file = none\n" );
fprintf( stderr, " don't strip first leading underscore from symbol\n" );
fprintf( stderr, " input is not PowerPC symbol dump\n" );
Cleanup();
exit( 1 );
} // Usage
/*******************************************************************
NAME: CreateExclusionList
SYNOPSIS: Reads a text file of excluded export names into memory,
sorts it and builds a lookup table compatible with
bsearch().
Returns -1 if failure or the count of the number
of items in the created array.
HISTORY:
********************************************************************/
int __cdecl qsortStrings ( const void * pa, const void * pb )
{
return strcmp( *((const char * *) pa), *((const char * *) pb) ) ;
}
int CreateExclusionList ( char * pszFileName,
void * * pvData,
char * * * apszStrings )
{
int cItems, i ;
int result = -1 ;
long cbFileSize, cbBlockSize ;
char * pszData = NULL,
* psz,
* pszNext ;
char * * ppszArray = NULL ;
char chRec [ MAX_LINE_FROM_COFF ] ;
FILE * pf = NULL ;
do
{
pf = fopen( pszFileName, "r" ) ;
if ( pf == NULL )
break;
if (fseek( pf, 0, SEEK_END ) == -1)
break;
cbFileSize = ftell( pf ) ;
if (fseek( pf, 0, SEEK_SET ) == -1)
break;
cbBlockSize = cbFileSize + (cbFileSize / 2) ;
pszData = (char *) malloc( cbBlockSize ) ;
if ( pszData == NULL )
break ;
for ( cItems = 0, pszNext = pszData ;
(!feof( pf )) && (psz = fgets( chRec, sizeof chRec, pf )) ; )
{
int lgt ;
char * pszEnd ;
while ( *psz <= ' ' && *psz != 0 )
{
psz++ ;
}
if ( (lgt = strlen( psz )) == 0 )
continue ;
pszEnd = psz + lgt ;
do
{
--pszEnd ;
} while ( pszEnd > psz && *pszEnd <= ' ' ) ;
lgt = (int)(++pszEnd - psz) ;
*pszEnd = 0 ;
if ( pszNext + lgt - pszData >= cbBlockSize )
{
cItems = -1 ;
break ;
}
strcpy( pszNext, psz ) ;
pszNext += lgt+1 ;
cItems++ ;
}
*pszNext = 0 ;
if ( cItems <= 0 )
{
if ( cItems == 0 )
result = 0 ;
break ;
}
ppszArray = (char * *) malloc( cItems * sizeof (char *) ) ;
if ( ppszArray == NULL )
break ;
for ( i = 0, pszNext = pszData ;
*pszNext ;
pszNext += strlen( pszNext ) + 1 )
{
ppszArray[i++] = pszNext ;
}
qsort( (void *) ppszArray,
cItems,
sizeof (char *),
& qsortStrings ) ;
result = cItems ;
} while ( 0 ) ;
if ( pf != NULL )
{
fclose( pf ) ;
}
if ( result <= 0 )
{
if ( pszData )
{
free( pszData ) ;
pszData = NULL ;
}
if ( ppszArray )
{
free( ppszArray ) ;
ppszArray = NULL ;
}
}
*pvData = (void *) pszData ;
*apszStrings = ppszArray ;
return result ;
}
int ExcludedSymbol ( char * pszSymbol )
{
if ( _apszExclusionArray == NULL )
{
return 0 ;
}
return bsearch( (void *) & pszSymbol,
(void *) _apszExclusionArray,
_cExclusionItems,
sizeof (char *),
& qsortStrings ) != NULL ;
}
int ValidSymbol ( const char * psz )
{
int i = 0 ;
for ( ; apszIgnore[i] ; i++ )
{
if ( _strnicmp( apszIgnore[i],
psz,
strlen( apszIgnore[i] ) ) == 0 )
return 0 ;
}
return 1 ;
}
// End of UIXPORT.C