Leaked source code of windows server 2003
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.

456 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  5. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  6. // PARTICULAR PURPOSE.
  7. //
  8. // Copyright 1998-2000 Microsoft Corporation. All Rights Reserved.
  9. //
  10. // PROGRAM: isrchdmp.cx
  11. //
  12. // PURPOSE: Illustrates a minimal query using Indexing Service.
  13. //
  14. // PLATFORM: Windows 2000
  15. //
  16. //--------------------------------------------------------------------------
  17. #ifndef UNICODE
  18. #define UNICODE
  19. #endif
  20. #include <stdio.h>
  21. #include <windows.h>
  22. #define DBINITCONSTANTS
  23. #include <oledberr.h>
  24. #include <oledb.h>
  25. #include <cmdtree.h>
  26. #include <ntquery.h>
  27. #include <filter.h>
  28. #include <filterr.h>
  29. #include "isearch.h"
  30. #include "array.hxx"
  31. extern CIPROPERTYDEF aCPPProperties[];
  32. extern unsigned cCPPProperties;
  33. //+-------------------------------------------------------------------------
  34. //
  35. // Template: XInterface
  36. //
  37. // Synopsis: Template for managing ownership of interfaces
  38. //
  39. //--------------------------------------------------------------------------
  40. template<class T> class XInterface
  41. {
  42. public:
  43. XInterface( T * p = 0 ) : _p( p ) {}
  44. ~XInterface() { if ( 0 != _p ) _p->Release(); }
  45. T * operator->() { return _p; }
  46. T * GetPointer() const { return _p; }
  47. IUnknown ** GetIUPointer() { return (IUnknown **) &_p; }
  48. T ** GetPPointer() { return &_p; }
  49. void ** GetQIPointer() { return (void **) &_p; }
  50. T * Acquire() { T * p = _p; _p = 0; return p; }
  51. private:
  52. T * _p;
  53. };
  54. const GUID guidStorage = PSGUID_STORAGE;
  55. typedef void (__stdcall * PFnCIShutdown)(void);
  56. typedef HRESULT (__stdcall * PFnMakeISearch)( ISearchQueryHits ** ppSearch,
  57. DBCOMMANDTREE * pRst,
  58. WCHAR const * pwcPath );
  59. typedef HRESULT (__stdcall * PFnLoadTextFilter)( WCHAR const * pwcPath,
  60. IFilter ** ppIFilter );
  61. PFnCIShutdown g_pCIShutdown = 0;
  62. PFnMakeISearch g_pMakeISearch = 0;
  63. PFnLoadTextFilter g_pLoadTextFilter = 0;
  64. #define UNICODE_PARAGRAPH_SEPARATOR 0x2029
  65. ULONG CountCR( WCHAR * pCur, ULONG cwc, WCHAR * &pwcPrev )
  66. {
  67. pwcPrev = pCur;
  68. WCHAR * pEnd = pCur + cwc;
  69. ULONG cCR = 0;
  70. while ( pCur < pEnd )
  71. {
  72. WCHAR c = *pCur;
  73. if ( L'\r' == c ||
  74. L'\n' == c ||
  75. UNICODE_PARAGRAPH_SEPARATOR == c )
  76. {
  77. cCR++;
  78. if ( ( L'\r' == c ) &&
  79. ( (pCur+1) < pEnd ) &&
  80. ( L'\n' == *(pCur+1) ) )
  81. pCur++;
  82. pwcPrev = pCur + 1;
  83. }
  84. pCur++;
  85. }
  86. return cCR;
  87. } //CountCR
  88. HRESULT WalkFile(
  89. TArray<FILTERREGION> & aHits,
  90. XInterface<IFilter> & xIFilter,
  91. WCHAR const * pwcFile,
  92. BOOL fPrintFile )
  93. {
  94. ULONG ulFlags;
  95. HRESULT hr = xIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS |
  96. IFILTER_INIT_CANON_HYPHENS |
  97. IFILTER_INIT_APPLY_INDEX_ATTRIBUTES,
  98. 0,
  99. 0,
  100. &ulFlags );
  101. if ( FAILED( hr ) )
  102. return hr;
  103. ULONG lenSoFar = 0;
  104. int cChunk = 0;
  105. BOOL fSeenProp = FALSE;
  106. ULONG iHit = 0;
  107. ULONG cLines = 1;
  108. const ULONG cwcBufSize = 65536;
  109. WCHAR *pwc = new WCHAR[cwcBufSize + 1];
  110. if ( 0 == pwc )
  111. return E_OUTOFMEMORY;
  112. STAT_CHUNK statChunk;
  113. hr = xIFilter->GetChunk( &statChunk );
  114. while( SUCCEEDED( hr ) ||
  115. ( FILTER_E_LINK_UNAVAILABLE == hr ) ||
  116. ( FILTER_E_EMBEDDING_UNAVAILABLE == hr ) )
  117. {
  118. if ( SUCCEEDED( hr ) && (statChunk.flags & CHUNK_TEXT) )
  119. {
  120. // read the contents only
  121. if ( ( guidStorage == statChunk.attribute.guidPropSet ) &&
  122. ( PRSPEC_PROPID == statChunk.attribute.psProperty.ulKind ) &&
  123. ( PID_STG_CONTENTS == statChunk.attribute.psProperty.propid ) )
  124. {
  125. if ( CHUNK_NO_BREAK != statChunk.breakType )
  126. {
  127. switch( statChunk.breakType )
  128. {
  129. case CHUNK_EOW:
  130. case CHUNK_EOS:
  131. break;
  132. case CHUNK_EOP:
  133. case CHUNK_EOC:
  134. cLines++;
  135. break;
  136. }
  137. }
  138. ULONG iIntoChunk = 0;
  139. ULONG cwcRetrieved;
  140. ULONG iPrevLine = ~0;
  141. do
  142. {
  143. cwcRetrieved = cwcBufSize;
  144. hr = xIFilter->GetText( &cwcRetrieved, pwc );
  145. pwc[cwcRetrieved] = 0;
  146. // The buffer may be filled with zeroes. Nice filter.
  147. if ( SUCCEEDED( hr ) )
  148. {
  149. if ( 0 != cwcRetrieved )
  150. cwcRetrieved = __min( cwcRetrieved,
  151. wcslen( pwc ) );
  152. while ( ( iHit < aHits.Count() ) &&
  153. ( aHits[iHit].idChunk == statChunk.idChunk ) &&
  154. ( aHits[iHit].cwcStart >= iIntoChunk ) &&
  155. ( aHits[iHit].cwcStart < ( iIntoChunk + cwcRetrieved ) ) )
  156. {
  157. WCHAR *pwcStart;
  158. ULONG iLine = cLines +
  159. CountCR( pwc,
  160. aHits[iHit].cwcStart - iIntoChunk,
  161. pwcStart );
  162. WCHAR *pwcEnd = wcschr( pwcStart, L'\r' );
  163. if ( 0 == pwcEnd )
  164. pwcEnd = wcschr( pwcStart, L'\n' );
  165. if ( 0 != pwcEnd )
  166. *pwcEnd = 0;
  167. if ( iLine != iPrevLine )
  168. {
  169. if ( fPrintFile )
  170. wprintf( L"%ws", pwcFile );
  171. wprintf( L"(%u): %ws\n", iLine, pwcStart );
  172. iPrevLine = iLine;
  173. }
  174. if ( 0 != pwcEnd )
  175. *pwcEnd = '\r';
  176. iHit++;
  177. }
  178. WCHAR * pwcDummy;
  179. cLines += CountCR( pwc, cwcRetrieved, pwcDummy );
  180. iIntoChunk += cwcRetrieved;
  181. }
  182. } while( SUCCEEDED( hr ) );
  183. }
  184. }
  185. hr = xIFilter->GetChunk ( &statChunk );
  186. }
  187. delete [] pwc;
  188. if ( FILTER_E_END_OF_CHUNKS == hr )
  189. hr = S_OK;
  190. return hr;
  191. } //WalkFile
  192. //+-------------------------------------------------------------------------
  193. //
  194. // Function: DoISearchQuery
  195. //
  196. // Synopsis: Creates and executes a query, then displays the results.
  197. //
  198. // Arguments: [pwcFilename] - Name of the file
  199. // [pwcQueryRestrition] - The actual query string
  200. // [fPrintFile] - whether to print the filename
  201. // [lcid] - Locale of the query
  202. // [ulDialect] - Dialect of tripolish, 1 or 2.
  203. //
  204. // Returns: HRESULT result of the query
  205. //
  206. //--------------------------------------------------------------------------
  207. HRESULT DoISearchQuery(
  208. WCHAR const * pwcFilename,
  209. WCHAR const * pwcQueryRestriction,
  210. BOOL fPrintFile,
  211. BOOL fDefineCPP,
  212. LCID lcid,
  213. ULONG ulDialect )
  214. {
  215. // Create an OLE DB query tree from a text restriction
  216. DBCOMMANDTREE * pTree;
  217. ULONG cDefinedProperties = fDefineCPP ? cCPPProperties : 0;
  218. HRESULT hr = CITextToSelectTreeEx( pwcQueryRestriction, // the query itself
  219. ulDialect, // dialect to use
  220. &pTree, // resulting tree
  221. cDefinedProperties, // C++ properties
  222. aCPPProperties, // C++ properties
  223. lcid ); // the locale
  224. if ( FAILED( hr ) )
  225. return hr;
  226. // Make the ISearchQueryHits object
  227. XInterface<ISearchQueryHits> xISearch;
  228. hr = g_pMakeISearch( xISearch.GetPPointer(),
  229. pTree,
  230. 0 );
  231. if ( FAILED( hr ) )
  232. return hr;
  233. XInterface<IFilter> xIFilter;
  234. #if 1
  235. hr = LoadIFilter( pwcFilename, 0, xIFilter.GetQIPointer() );
  236. if ( FAILED( hr ) )
  237. {
  238. // Fall back on the plain text filter
  239. hr = g_pLoadTextFilter( pwcFilename, xIFilter.GetPPointer() );
  240. if ( FAILED( hr ) )
  241. return hr;
  242. }
  243. #else
  244. // LIFF_LOAD_DEFINED_FILTER: Load the filter found for the file
  245. // LIFF_IMPLEMENT_TEXT_FILTER_FALLBACK_POLICY: Use the registry key to check to fallback
  246. // LIFF_FORCE_TEXT_FILTER_FALLBACK: Always fall back to the text filter if no other is available
  247. hr = LoadIFilterEx( pwcFilename,
  248. LIFF_IMPLEMENT_TEXT_FILTER_FALLBACK_POLICY,
  249. IID_IFilter,
  250. xIFilter.GetQIPointer() );
  251. if ( FAILED( hr ) )
  252. {
  253. printf( "can't load filter: %#x\n", hr );
  254. return hr;
  255. }
  256. #endif
  257. ULONG ulFlags;
  258. hr = xIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS |
  259. IFILTER_INIT_CANON_HYPHENS |
  260. IFILTER_INIT_APPLY_INDEX_ATTRIBUTES,
  261. 0,
  262. 0,
  263. &ulFlags );
  264. if ( FAILED( hr ) )
  265. return hr;
  266. hr = xISearch->Init( xIFilter.GetPointer(), ulFlags );
  267. if ( FAILED( hr ) )
  268. return hr;
  269. //
  270. // Retrieve all the hit info. the info is wrt output from the IFilter.
  271. // a separate pass over a different IFilter is needed to match up
  272. // text to the hit info.
  273. //
  274. TArray<FILTERREGION> aHits;
  275. ULONG cRegions;
  276. FILTERREGION* aRegion;
  277. hr = xISearch->NextHitOffset( &cRegions, &aRegion );
  278. while ( S_OK == hr )
  279. {
  280. for ( ULONG i = 0; i < cRegions; i++ )
  281. aHits.Append( aRegion[i] );
  282. CoTaskMemFree( aRegion );
  283. hr = xISearch->NextHitOffset( &cRegions, &aRegion );
  284. }
  285. #if 0
  286. for ( ULONG i = 0; i < aHits.Count(); i++ )
  287. printf( "hit %d, chunk %d start %d extent %d\n",
  288. i, aHits[i].idChunk, aHits[i].cwcStart, aHits[i].cwcExtent );
  289. #endif
  290. return WalkFile( aHits, xIFilter, pwcFilename, fPrintFile );
  291. } //DoISearchQuery
  292. //+-------------------------------------------------------------------------
  293. //
  294. // Function: GetQueryFunctions
  295. //
  296. // Synopsis: Loads needed undocumented functions from query.dll.
  297. //
  298. // Returns: The module handle or 0 on failure.
  299. //
  300. //--------------------------------------------------------------------------
  301. HINSTANCE GetQueryFunctions()
  302. {
  303. HINSTANCE h = LoadLibrary( L"query.dll" );
  304. if ( 0 != h )
  305. {
  306. #ifdef _WIN64
  307. char const * pcCIShutdown = "?CIShutdown@@YAXXZ";
  308. char const * pcMakeISearch = "?MakeISearch@@YAJPEAPEAUISearchQueryHits@@PEAVCDbRestriction@@PEBG@Z";
  309. #else
  310. char const * pcCIShutdown = "?CIShutdown@@YGXXZ";
  311. char const * pcMakeISearch = "?MakeISearch@@YGJPAPAUISearchQueryHits@@PAVCDbRestriction@@PBG@Z";
  312. #endif
  313. g_pCIShutdown = (PFnCIShutdown) GetProcAddress( h, pcCIShutdown );
  314. if ( 0 == g_pCIShutdown )
  315. {
  316. FreeLibrary( h );
  317. return 0;
  318. }
  319. g_pMakeISearch = (PFnMakeISearch) GetProcAddress( h, pcMakeISearch );
  320. if ( 0 == g_pMakeISearch )
  321. {
  322. FreeLibrary( h );
  323. return 0;
  324. }
  325. g_pLoadTextFilter = (PFnLoadTextFilter) GetProcAddress( h, "LoadTextFilter" );
  326. if ( 0 == g_pLoadTextFilter )
  327. {
  328. FreeLibrary( h );
  329. return 0;
  330. }
  331. }
  332. return h;
  333. } //GetQueryFunctions
  334. HINSTANCE PrepareForISearch()
  335. {
  336. return GetQueryFunctions();
  337. } //DoneWithISearch
  338. void DoneWithISearch( HINSTANCE h )
  339. {
  340. g_pCIShutdown();
  341. FreeLibrary( h );
  342. } //DoneWithISearch
  343. //+-------------------------------------------------------------------------
  344. //
  345. // Function: DoISearch
  346. //
  347. // Synopsis: Invoke ISearch on the file
  348. //
  349. // Arguments: [pwcRestriction] -- the query
  350. // [pwcFilename] -- the file
  351. // [fPrintFile] -- whether to print the filename
  352. // [fDefineCPP] -- TRUE to define the C++ properties func and class
  353. // [lcid] -- locale of the query
  354. // [ulDialect] -- the dialect of the query language
  355. //
  356. //--------------------------------------------------------------------------
  357. HRESULT DoISearch(
  358. WCHAR const * pwcRestriction,
  359. WCHAR const * pwcFilename,
  360. BOOL fPrintFile,
  361. BOOL fDefineCPP,
  362. LCID lcid,
  363. ULONG ulDialect )
  364. {
  365. // Run the query
  366. return DoISearchQuery( pwcFilename, pwcRestriction, fPrintFile, fDefineCPP, lcid, ulDialect );
  367. } //DoISearch