windows-nt/Source/XPSP1/NT/inetsrv/query/apps/ci/isrch.cxx

429 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1998-2000 Microsoft Corporation. All Rights Reserved.
//
// PROGRAM: isrchdmp.cx
//
// PURPOSE: Illustrates a minimal query using Indexing Service.
//
// PLATFORM: Windows 2000
//
//--------------------------------------------------------------------------
#ifndef UNICODE
#define UNICODE
#endif
#include <stdio.h>
#include <windows.h>
#define DBINITCONSTANTS
#include <oledberr.h>
#include <oledb.h>
#include <cmdtree.h>
#include <ntquery.h>
#include <filter.h>
#include <filterr.h>
#include "isearch.h"
#include "array.hxx"
extern CIPROPERTYDEF aCPPProperties[];
extern unsigned cCPPProperties;
//+-------------------------------------------------------------------------
//
// Template: XInterface
//
// Synopsis: Template for managing ownership of interfaces
//
//--------------------------------------------------------------------------
template<class T> class XInterface
{
public:
XInterface( T * p = 0 ) : _p( p ) {}
~XInterface() { if ( 0 != _p ) _p->Release(); }
T * operator->() { return _p; }
T * GetPointer() const { return _p; }
IUnknown ** GetIUPointer() { return (IUnknown **) &_p; }
T ** GetPPointer() { return &_p; }
void ** GetQIPointer() { return (void **) &_p; }
T * Acquire() { T * p = _p; _p = 0; return p; }
private:
T * _p;
};
const GUID guidStorage = PSGUID_STORAGE;
typedef void (__stdcall * PFnCIShutdown)(void);
typedef HRESULT (__stdcall * PFnMakeISearch)( ISearchQueryHits ** ppSearch,
DBCOMMANDTREE * pRst,
WCHAR const * pwcPath );
typedef HRESULT (__stdcall * PFnLoadTextFilter)( WCHAR const * pwcPath,
IFilter ** ppIFilter );
PFnCIShutdown g_pCIShutdown = 0;
PFnMakeISearch g_pMakeISearch = 0;
PFnLoadTextFilter g_pLoadTextFilter = 0;
#define UNICODE_PARAGRAPH_SEPARATOR 0x2029
ULONG CountCR( WCHAR * pCur, ULONG cwc, WCHAR * &pwcPrev )
{
pwcPrev = pCur;
WCHAR * pEnd = pCur + cwc;
ULONG cCR = 0;
while ( pCur < pEnd )
{
WCHAR c = *pCur;
if ( L'\r' == c ||
L'\n' == c ||
UNICODE_PARAGRAPH_SEPARATOR == c )
{
cCR++;
if ( ( L'\r' == c ) &&
( (pCur+1) < pEnd ) &&
( L'\n' == *(pCur+1) ) )
pCur++;
pwcPrev = pCur + 1;
}
pCur++;
}
return cCR;
} //CountCR
HRESULT WalkFile(
TArray<FILTERREGION> & aHits,
XInterface<IFilter> & xIFilter,
WCHAR const * pwcFile,
BOOL fPrintFile )
{
ULONG ulFlags;
HRESULT hr = xIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS |
IFILTER_INIT_CANON_HYPHENS |
IFILTER_INIT_APPLY_INDEX_ATTRIBUTES,
0,
0,
&ulFlags );
if ( FAILED( hr ) )
return hr;
ULONG lenSoFar = 0;
int cChunk = 0;
BOOL fSeenProp = FALSE;
ULONG iHit = 0;
ULONG cLines = 1;
const ULONG cwcBufSize = 65536;
WCHAR *pwc = new WCHAR[cwcBufSize + 1];
if ( 0 == pwc )
return E_OUTOFMEMORY;
STAT_CHUNK statChunk;
hr = xIFilter->GetChunk( &statChunk );
while( SUCCEEDED( hr ) ||
( FILTER_E_LINK_UNAVAILABLE == hr ) ||
( FILTER_E_EMBEDDING_UNAVAILABLE == hr ) )
{
if ( SUCCEEDED( hr ) && (statChunk.flags & CHUNK_TEXT) )
{
// read the contents only
if ( ( guidStorage == statChunk.attribute.guidPropSet ) &&
( PRSPEC_PROPID == statChunk.attribute.psProperty.ulKind ) &&
( PID_STG_CONTENTS == statChunk.attribute.psProperty.propid ) )
{
if ( CHUNK_NO_BREAK != statChunk.breakType )
{
switch( statChunk.breakType )
{
case CHUNK_EOW:
case CHUNK_EOS:
break;
case CHUNK_EOP:
case CHUNK_EOC:
cLines++;
break;
}
}
ULONG iIntoChunk = 0;
ULONG cwcRetrieved;
ULONG iPrevLine = ~0;
do
{
cwcRetrieved = cwcBufSize;
hr = xIFilter->GetText( &cwcRetrieved, pwc );
pwc[cwcRetrieved] = 0;
// The buffer may be filled with zeroes. Nice filter.
if ( SUCCEEDED( hr ) )
{
if ( 0 != cwcRetrieved )
cwcRetrieved = __min( cwcRetrieved,
wcslen( pwc ) );
while ( ( iHit < aHits.Count() ) &&
( aHits[iHit].idChunk == statChunk.idChunk ) &&
( aHits[iHit].cwcStart >= iIntoChunk ) &&
( aHits[iHit].cwcStart < ( iIntoChunk + cwcRetrieved ) ) )
{
WCHAR *pwcStart;
ULONG iLine = cLines +
CountCR( pwc,
aHits[iHit].cwcStart - iIntoChunk,
pwcStart );
WCHAR *pwcEnd = wcschr( pwcStart, L'\r' );
if ( 0 == pwcEnd )
pwcEnd = wcschr( pwcStart, L'\n' );
if ( 0 != pwcEnd )
*pwcEnd = 0;
if ( iLine != iPrevLine )
{
if ( fPrintFile )
wprintf( L"%ws", pwcFile );
wprintf( L"(%u): %ws\n", iLine, pwcStart );
iPrevLine = iLine;
}
if ( 0 != pwcEnd )
*pwcEnd = '\r';
iHit++;
}
WCHAR * pwcDummy;
cLines += CountCR( pwc, cwcRetrieved, pwcDummy );
iIntoChunk += cwcRetrieved;
}
} while( SUCCEEDED( hr ) );
}
}
hr = xIFilter->GetChunk ( &statChunk );
}
delete [] pwc;
if ( FILTER_E_END_OF_CHUNKS == hr )
hr = S_OK;
return hr;
} //WalkFile
//+-------------------------------------------------------------------------
//
// Function: DoQuery
//
// Synopsis: Creates and executes a query, then displays the results.
//
// Arguments: [pwcFilename] - Name of the file
// [pwcQueryRestrition] - The actual query string
// [fPrintFile] - whether to print the filename
// [lcid] - Locale of the query
//
// Returns: HRESULT result of the query
//
//--------------------------------------------------------------------------
HRESULT DoQuery(
WCHAR const * pwcFilename,
WCHAR const * pwcQueryRestriction,
BOOL fPrintFile,
BOOL fDefineCPP,
LCID lcid )
{
// Create an OLE DB query tree from a text restriction
DBCOMMANDTREE * pTree;
ULONG cDefinedProperties = fDefineCPP ? cCPPProperties : 0;
HRESULT hr = CITextToSelectTree( pwcQueryRestriction, // the query itself
&pTree, // resulting tree
cDefinedProperties, // C++ properties
aCPPProperties, // C++ properties
lcid ); // default locale
if ( FAILED( hr ) )
return hr;
// Make the ISearchQueryHits object
XInterface<ISearchQueryHits> xISearch;
hr = g_pMakeISearch( xISearch.GetPPointer(),
pTree,
0 );
if ( FAILED( hr ) )
return hr;
XInterface<IFilter> xIFilter;
hr = LoadIFilter( pwcFilename, 0, xIFilter.GetQIPointer() );
if ( FAILED( hr ) )
{
// Fall back on the plain text filter
hr = g_pLoadTextFilter( pwcFilename, xIFilter.GetPPointer() );
if ( FAILED( hr ) )
return hr;
}
ULONG ulFlags;
hr = xIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS |
IFILTER_INIT_CANON_HYPHENS |
IFILTER_INIT_APPLY_INDEX_ATTRIBUTES,
0,
0,
&ulFlags );
if ( FAILED( hr ) )
return hr;
hr = xISearch->Init( xIFilter.GetPointer(), ulFlags );
if ( FAILED( hr ) )
return hr;
//
// Retrieve all the hit info. the info is wrt output from the IFilter.
// a separate pass over a different IFilter is needed to match up
// text to the hit info.
//
TArray<FILTERREGION> aHits;
ULONG cRegions;
FILTERREGION* aRegion;
hr = xISearch->NextHitOffset( &cRegions, &aRegion );
while ( S_OK == hr )
{
for ( ULONG i = 0; i < cRegions; i++ )
aHits.Append( aRegion[i] );
CoTaskMemFree( aRegion );
hr = xISearch->NextHitOffset( &cRegions, &aRegion );
}
#if 0
for ( ULONG i = 0; i < aHits.Count(); i++ )
printf( "hit %d, chunk %d start %d extent %d\n",
i, aHits[i].idChunk, aHits[i].cwcStart, aHits[i].cwcExtent );
#endif
return WalkFile( aHits, xIFilter, pwcFilename, fPrintFile );
} //DoQuery
//+-------------------------------------------------------------------------
//
// Function: GetQueryFunctions
//
// Synopsis: Loads needed undocumented functions from query.dll.
//
// Returns: The module handle or 0 on failure.
//
//--------------------------------------------------------------------------
HINSTANCE GetQueryFunctions()
{
HINSTANCE h = LoadLibrary( L"query.dll" );
if ( 0 != h )
{
#ifdef _WIN64
char const * pcCIShutdown = "?CIShutdown@@YAXXZ";
char const * pcMakeISearch = "?MakeISearch@@YAJPEAPEAUISearchQueryHits@@PEAVCDbRestriction@@PEBG@Z";
#else
char const * pcCIShutdown = "?CIShutdown@@YGXXZ";
char const * pcMakeISearch = "?MakeISearch@@YGJPAPAUISearchQueryHits@@PAVCDbRestriction@@PBG@Z";
#endif
g_pCIShutdown = (PFnCIShutdown) GetProcAddress( h, pcCIShutdown );
if ( 0 == g_pCIShutdown )
{
FreeLibrary( h );
return 0;
}
g_pMakeISearch = (PFnMakeISearch) GetProcAddress( h, pcMakeISearch );
if ( 0 == g_pMakeISearch )
{
FreeLibrary( h );
return 0;
}
g_pLoadTextFilter = (PFnLoadTextFilter) GetProcAddress( h, "LoadTextFilter" );
if ( 0 == g_pLoadTextFilter )
{
FreeLibrary( h );
return 0;
}
}
return h;
} //GetQueryFunctions
HINSTANCE PrepareForISearch()
{
return GetQueryFunctions();
} //DoneWithISearch
void DoneWithISearch( HINSTANCE h )
{
g_pCIShutdown();
FreeLibrary( h );
} //DoneWithISearch
//+-------------------------------------------------------------------------
//
// Function: DoISearch
//
// Synopsis: Invoke ISearch on the file
//
// Arguments: [pwcRestriction] -- the query
// [pwcFilename] -- the file
// [fPrintFile] -- whether to print the filename
// [lcid] -- locale of the query
//
//--------------------------------------------------------------------------
HRESULT DoISearch(
WCHAR const * pwcRestriction,
WCHAR const * pwcFilename,
BOOL fPrintFile,
BOOL fDefineCPP,
LCID lcid )
{
// Run the query
return DoQuery( pwcFilename, pwcRestriction, fPrintFile, fDefineCPP, lcid );
} //DoISearch