Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

335 lines
13 KiB

/**********************************************************************
// SEARCH.C
//
// Copyright (c) 1992 - Microsoft Corp.
// All rights reserved.
// Microsoft Confidential
//
// Entry point for string search criteria.
//
// TABS = 3
// johnhe - 04-26-92
**********************************************************************/
#include "shellprv.h"
#pragma hdrstop
#pragma warning( disable:4001 ) // Disable new type remark warning
//*********************************************************************
// Local function prototypes.
//*********************************************************************
void BldSearchLsts ( LPGREPINFO lpgi, LPSTR pStrLst, LPSTR pNotList );
static LPSTR s_pSrchStrLst = NULL; // Ptr to normal search string list
//*********************************************************************
// Builds allocates search buffers and builds search list trees.
//
// The format of the pStrLst and pNotLst is multiple zero terminated
// strings with a zero length string marking the end of the list.
//
// "string1",0,"string2",0,"string3",0,"...",0,0
//
// int InitGrepInfo( LPSTR pStrLst, LPSTR pNotList, unsigned uOpts )
//
// ARGUMENTS:
// pStrLst - Ptr to list of string to try to match
// pNotLst - Ptr to list of string which must not match
// uOpts - Search options of FLG_REGULAR and FLG_CASE
// RETURNS:
// int - OK is no errors else ERR_NOMEMORY, ERR_MEMCORUPT,
// ERR_STRLST_LEN, or ERR_SRCH_EXPRESSION
//
//*********************************************************************
LPGREPINFO InitGrepInfo( LPSTR pStrLst, LPSTR pNotList, unsigned uOpts )
{
int i; // Loop indice
LPGREPINFO lpgi;
// Make sure there is at least one string to match in at least
// one of the search lists and set flag if no normal srch strings.
if ( pStrLst[ 0 ] == '\0' && pNotList[ 0 ] == '\0' )
return( OK );
s_pSrchStrLst = pStrLst;
if ( (lpgi = InitGrepBufs()) == NULL )
return( NULL );
if ( (uOpts & FLG_REGULAR) != FALSE ) // Use regular expression (/R) ?
lpgi->addstr = addexpr; // Then add expression to list
else
lpgi->addstr = addstring; // Else treat strings literally
// Set if case sensitivity
lpgi->CaseSen = ((uOpts & FLG_CASE) ? TRUE : FALSE);
// Set longjmp to allow aborting on errors
_try
{
BldSearchLsts( lpgi, pStrLst, pNotList );
if ( !(uOpts & FLG_REGULAR) ) // If not using expressions
{
lpgi->find = findlist; // Assume finding many
for ( i = 0; i < 2; i++ )
{
_fmemset(lpgi->ge.td1, (int)(lpgi->ge.ShortStrLen + 1), TRTABLEN); // Init lpgi->ge.td1 tables
enumstrings(lpgi); // Build lpgi->ge.td1 table
if (lpgi->ge.StrCount == 1 && lpgi->CaseSen)
lpgi->find = findone; // Find one case-sensitive string
else
lpgi->find = findlist; // Assume finding many
SwapSrchTables(lpgi); // Do the data swap
}
}
else if (lpgi->find == NULL)
lpgi->find = findexpr; // Else find expressions
}
// Let the debugger get a chance at the exceptions first...
_except(SetErrorMode(SEM_NOGPFAULTERRORBOX),UnhandledExceptionFilter(GetExceptionInformation()))
{
FreeGrepBufs(lpgi);
return NULL ;
}
return( lpgi );
}
//*********************************************************************
// Initializes the search tree data for both the search list and
// not search list.
//
// void BldSearchLsts( LPSTR pStrLst, LPSTR pNotList )
//
// ARGUMENTS:
// pStrLst - Ptr to list of strings or expression to match
// pNotLst - Ptr to list of strings or expression which must not match
// RETURNS:
// void
//
//*********************************************************************
void BldSearchLsts( LPGREPINFO lpgi, LPSTR pStrLst, LPSTR pNotList )
{
LPSTR szNext; // Ptr to next string to add
int i; // Loop indice
int iStrLen; // Length of current string
// Loop 3 times. First iteration add all search strings to normal
// search list, 2nd iteration add all /NOT string to the normal
// search list and then swap the search data so that on the
// 3rd iteration all the /NOT string will be added to the /NOT
// search list. Then swap the data again to restore the original.
for ( szNext = pStrLst, i = 0; i < 3; i++ )
{
while ( *szNext != '\0' )
{
iStrLen = (int)lstrlenA( szNext );
// If doing string search make sure this is not a duplicate
// before adding it to the search tree.
if ( lpgi->addstr == addexpr ||
findlist( lpgi, szNext, szNext + iStrLen ) == NULL )
(*lpgi->addstr)( lpgi, szNext, iStrLen ); // Add string to list
szNext += iStrLen + 1;
}
if ( i == 1 ) // Is this the 2nd iteration
SwapSrchTables(lpgi); // Do the data swap
// Set string ptr to /NOT list for 2nd and 3rd iterations.
szNext = pNotList;
}
SwapSrchTables(lpgi); // Restore the original data area
}
//*********************************************************************
// Reads in portions of an open file and search the strings initialized
// by BldSearchLsts().
//
// If (fFlags & FLG_FIND_FILE) will continue reading thru the file until
// a matching search string is found or the end of the file is reached.
// If there are string specified in the /NOT list the file will continue
// to be scanned until either a string the the /NOT list is detected
// or the end of the file is reached.
//
// If !(fFlags & FLG_FIND_FILE) the file will be searched for lines
// which match containing a matching string and then the user supplied
// callback will be called for each line which contains a match or
// does not contain a match, depending on the bits in fFlags.
//
//
// NOTE:
// InitSearchInfo() must be called to setup the search information
// and intialize the search buffers before this function is called
// the first time.
//
// int FileFindGrep( HANDLE fh, unsigned fFlags, FIND_CALLBACK FindCb )
//
// ARGUMENTS:
// fHandle - Open DOS file handle of file to search
// fFlags - Operation flags can be a combination of:
// FLG_FIND_FILE - Only try to locate the file (EXCLUSIVE)
// FLG_FIND_NOMATCH - Display non-matching lines
// FLG_FIND_MATCH - Display matching lines
// FLG_FIND_COUNT - Display on count of matching lines
// FLG_FIND_LINENO - Display line numbers on output
// FindCb - Call function for displaying matching strings or NULL
// if (fFlags & FLG_FIND_FILE).
// RETURNS:
// int - If (fFlags & FLG_FIND_FILE) returns TRUE if at least one
// string match from pStrLst and no string match from pNotLst
// else FALSE. If !(fFlags & FLG_FIND_FILE) returns OK
// if no errors else returns ERR_FILE_READ or any value
// returned by a callback function.
//
//*********************************************************************
int FileFindGrep( LPGREPINFO lpgi, HANDLE fh, unsigned fFlags,
long (far pascal *AppCb)( int Func,
unsigned uArg0,
void far *pArg1,
unsigned long ulArg2 ) )
{
register LPSTR BufPtr; // Buffer pointer
LPSTR EndBuf; // End of buffer
LPSTR pchChar; // Ptr to matching string in buffer
#ifdef DO_CALLBACK
TCHAR *pchBegin; // Ptr to start of line
TCHAR *pchEnd; // Ptr to end of line
#endif
int iStatus; //
DWORD ByteCount; // Byte count
unsigned TailLen; // Length of buffer tail
unsigned long ulLineNum; // Current line number in the file
unsigned long ulMatchCnt; // Count of lines containing match
lpgi->ReadBuf[ 3 ] = '\n'; // Mark beginning with newline
BufPtr = lpgi->ReadBuf + 4; // Set buf ptr to after newline
TailLen = 0; // No buffer tail yet
ulLineNum = 0UL; // Start with line 1
ulMatchCnt = 0UL; // Zero the match count
iStatus = OK; // Assume no errors to start
// Loop filling the buffer and then searching it
while ( ReadFile(fh, BufPtr, SectorBased( FILBUFLEN - TailLen),
&ByteCount, NULL)
&& (ByteCount + TailLen != 0))
{
if ( ByteCount == 0 )
{ // If buffer tail is all that's left
TailLen = 0; // Set tail length to zero
*BufPtr++ = '\r'; // Add end of line sequence
*BufPtr++ = '\n';
EndBuf = BufPtr; // Note end of buffer
}
else // Else start next read
{ // Find length of partial line
TailLen = (unsigned)preveol( BufPtr + ByteCount - 1 );
if ( TailLen == ByteCount ) // Find tail length after last LF
{
TailLen = 0; // No linefeeds in buffer
EndBuf = BufPtr + ByteCount;
}
else
EndBuf = BufPtr + ByteCount - TailLen;
}
pchChar = lpgi->ReadBuf + 4;
// Loop searching thru the buffer for matching strings
while ( pchChar != NULL &&
EndBuf > pchChar &&
(EndBuf - pchChar) >= lpgi->ge.ShortStrLen )
{
if ( !(fFlags & FIND_FILE) )
{
#ifdef DO_CALLBACKS
ulLineNum++; // Increment the line count
pchBegin = pchChar;
pchEnd = NextEol( pchChar, EndBuf );
if ( (pchChar = (*find)( pchChar, pchEnd )) != NULL )
{
ulMatchCnt++;
if ( !(fFlags & FIND_NOMATCH) &&
!(fFlags & FIND_COUNT) )
iStatus = CB_FindMatch( pchEnd - pchBegin,
pchBegin, ulLineNum );
}
else if ( (fFlags & FLG_FIND_NOMATCH) )
iStatus = CB_FindMatch( pchEnd - pchBegin, pchBegin,
ulLineNum );
if ( iStatus != OK )
return( iStatus );
pchChar = pchEnd;
#endif // DO_CALLBACKS
}
else if ( (pchChar = (*lpgi->find)( lpgi, pchChar, EndBuf )) != NULL )
{
// If we looking for /NOT strings the
// findfile fails unless NoSrchStr == TRUE, if we are not
// looking for /NOT strings it means we found a normal
// string so see if there are any not strings.
if ( (fFlags & FIND_NOT) )
{
SwapSrchTables(lpgi); // Restore the normal data area
return( FALSE ); // Always FALSE if /NOT strs found
}
else if ( lpgi->geNot.TblEntriesUsed <= 1 ) // Are there any /NOT strings
return( TRUE ); // Found a match and no /NOT strings
else
{
SwapSrchTables(lpgi); // Need to search for /NOT strings
fFlags |= FIND_NOT; // Signal we've changed the data
}
}
// Copy tail to head of buffer
}
if ( TailLen != 0 )
hmemcpy( lpgi->ReadBuf + 4, EndBuf, TailLen );
BufPtr = lpgi->ReadBuf + TailLen + 4; // Skip over tail
// If our last read returned no bytes
}
if ( !(fFlags & FIND_FILE) )
#ifdef DOCALLBACKS
return( CB_FindCount( ulMatchCnt ) );
#else
return(1);
#endif //CALLBACK
else if ( !(fFlags & FIND_NOT) )
return( (s_pSrchStrLst[ 0 ] == '\0') ? TRUE : FALSE );
SwapSrchTables(lpgi); // Restore the normal data area
return( TRUE ); // No /NOT strings found success
}
//*********************************************************************
//*********************************************************************
LPSTR NextEol( LPSTR pchChar, LPSTR EndBuf )
{
pchChar++; // String starts with /r
while( pchChar < EndBuf && *pchChar != 0x0A )
pchChar++;
return( pchChar );
}