//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1998. // // File: TxtSinkDump.cxx // // Contents: Contains an implementation of ICiCTextSink interface. // // History: Jan-13-97 KLam Created // //---------------------------------------------------------------------------- #define WIN32_LEAN_AND_MEAN extern "C" { #include #include #include } #include #include #include #include #include #include #include #include #include // registration functions #include "FiltStat.hxx" static long glcInstances = 0; static WCHAR gwszModule[MAX_PATH]; static WCHAR gwszFilterStatusDumpCLSID[] = L"{3ce7c910-8d72-11d1-8f76-00a0c91917f5}"; static GUID CLSID_CFilterStatusDump = { 0x3ce7c910, 0x8d72, 0x11d1, { 0x8f, 0x76, 0x00, 0xa0, 0xc9, 0x19, 0x17, 0xf5 } }; static const WCHAR gwszDescription [] = L"Filtering Status Dumper"; // // CFilterStatusDump Methods // CFilterStatusDump::CFilterStatusDump () : _pfOutput(0), _fSuccessReport( FALSE ), _cRefs ( 1 ) { InterlockedIncrement ( &glcInstances ); } CFilterStatusDump::~CFilterStatusDump () { if ( 0 != _pfOutput ) fclose( _pfOutput ); InterlockedDecrement( &glcInstances ); } //+--------------------------------------------------------------------------- // // Member: CFilterStatusDump::QueryInterface // // Synopsis: Returns interfaces to IID_IUknown, IID_ICiCTextSink // // Arguments: [riid] -- IID of new interface // [ppvObject] -- New interface * returned here // // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- STDMETHODIMP CFilterStatusDump::QueryInterface ( REFIID riid, void ** ppvObject ) { //Win4Assert ( 0 != ppvObject ); if ( IID_IUnknown == riid ) { AddRef (); *ppvObject = (void *)(IUnknown *) this; return S_OK; } else if ( IID_IFilterStatus == riid ) { AddRef (); *ppvObject = (void *)(IFilterStatus *) this; return S_OK; } else { *ppvObject = 0; return E_NOINTERFACE; } } //+--------------------------------------------------------------------------- // // Member: CFilterStatusDump::AddRef // // Synopsis: Increments the reference count on the object // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CFilterStatusDump::AddRef () { return InterlockedIncrement ( (long *)&_cRefs ); } //+--------------------------------------------------------------------------- // // Member: CFilterStatusDump::Release // // Synopsis: Decrements the reference count on the object. // If the reference count reaches 0, the object is deleted. // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CFilterStatusDump::Release () { ULONG cTemp = InterlockedDecrement ( (long *)&_cRefs ); if ( 0 == cTemp ) delete this; return cTemp; } //+--------------------------------------------------------------------------- // // Member: CFilterStatusDump::Initialize // // Synopsis: Creates or opens the text sink dump file. If the file already // exists, it sets the file pointer to the end of the file. // // Arguments: [pwszSessionId] -- String identifying current session // [pwszSessionPath] -- Path containing current session catalog // [pIndexClientInfo] -- Pointer to Client Info context // [fQuery] -- Boolean indicating whether the incoming // text is a query // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- STDMETHODIMP CFilterStatusDump::Initialize ( WCHAR const * pwszCatalog, WCHAR const * pwszCatalogPath ) { CLock lock( _mutex ); SCODE sc = E_FAIL; // // Clean up from previous state, if any. // if ( 0 != _pfOutput ) { fclose( _pfOutput ); _pfOutput = 0; } CTranslateSystemExceptions translate; TRY { // // Locate path of dump file in registry. // unsigned ccCat = wcslen( pwszCatalog ); unsigned const ccBase = sizeof(wcsRegJustCatalogsSubKey)/sizeof(WCHAR) - 1; XGrowable xTemp; xTemp.SetSize( ccBase + ccCat + 2 ); RtlCopyMemory( xTemp.Get(), wcsRegJustCatalogsSubKey, ccBase * sizeof(WCHAR) ); xTemp[ccBase] = L'\\'; RtlCopyMemory( xTemp.Get() + ccBase + 1, pwszCatalog, (ccCat + 1) * sizeof(WCHAR) ); // 1 for null CRegAccess reg( RTL_REGISTRY_CONTROL, xTemp.Get() ); XGrowable xFile; reg.Get( L"FilterStatusLog", xFile.Get(), xFile.Count() ); _fSuccessReport = (reg.Read( L"FilterStatusReportSuccess", 0, 0, 1 ) != 0); // // Open file // _pfOutput = _wfopen( xFile.Get(), L"a+" ); if ( 0 == _pfOutput ) { THROW( CException( ERROR_FILE_NOT_FOUND ) ); } sc = S_OK; } CATCH( CException, e ) { sc = GetOleError( e ); } END_CATCH return sc; } STDMETHODIMP CFilterStatusDump::PreFilter( WCHAR const * pwszPath ) { return S_OK; } STDMETHODIMP CFilterStatusDump::FilterLoad( WCHAR const * pwszPath, SCODE scFilterStatus ) { if ( FAILED(scFilterStatus) && 0 != _pfOutput ) { // // Convert to narrow string. // XGrowable xTemp; DWORD cbConvert = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pwszPath, wcslen( pwszPath ) + 1, xTemp.Get(), xTemp.Count(), 0, 0 ); CLock lock( _mutex ); if ( 0 == cbConvert ) { xTemp[cbConvert] = 0; fprintf( _pfOutput, "Error %#x loading filter for \"%ws\"\n", scFilterStatus, pwszPath ); } else { xTemp[cbConvert] = 0; fprintf( _pfOutput, "Error %#x loading filter for \"%s\"\n", scFilterStatus, xTemp.Get() ); } fflush( _pfOutput ); } return S_OK; } STDMETHODIMP CFilterStatusDump::PostFilter( WCHAR const * pwszPath, SCODE scFilterStatus ) { if ( (_fSuccessReport || FAILED(scFilterStatus)) && 0 != _pfOutput ) { // // Convert to narrow string. // XGrowable xTemp; DWORD cbConvert = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pwszPath, wcslen( pwszPath ) + 1, xTemp.Get(), xTemp.Count(), 0, 0 ); CLock lock( _mutex ); if ( 0 == cbConvert ) { xTemp[cbConvert] = 0; if ( SUCCEEDED(scFilterStatus) ) fprintf( _pfOutput, "ok: \"%ws\"\n", pwszPath ); else fprintf( _pfOutput, "Error %#x indexing \"%ws\"\n", scFilterStatus, pwszPath ); } else { xTemp[cbConvert] = 0; if ( SUCCEEDED(scFilterStatus) ) fprintf( _pfOutput, "ok \"%s\"\n", xTemp.Get() ); else fprintf( _pfOutput, "Error %#x indexing \"%s\"\n", scFilterStatus, xTemp.Get() ); } fflush( _pfOutput ); } return S_OK; } // // CFilterStatusCF Methods // //+--------------------------------------------------------------------------- // // Member: CFilterStatusCF::CFilterStatusCF // // Synopsis: Constructor // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- CFilterStatusCF::CFilterStatusCF () : _cRefs (1) { InterlockedIncrement ( &glcInstances ); } //+--------------------------------------------------------------------------- // // Member: CFilterStatusCF::~CFilterStatusCF // // Synopsis: Destructor // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- CFilterStatusCF::~CFilterStatusCF () { //Win4Assert( _cRefs == 0); //Win4Assert( glcInstances != 0 ); InterlockedDecrement( &glcInstances ); } //+--------------------------------------------------------------------------- // // Member: CFilterStatusCF::QueryInterface // // Synopsis: Rebind to other interface // // Arguments: [riid] -- IID of new interface // [ppvObject] -- New interface * returned here // // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- STDMETHODIMP CFilterStatusCF::QueryInterface ( REFIID riid, void ** ppvObject ) { //Win4Assert ( NULL != ppvObject ); if ( IID_IUnknown == riid ) { AddRef (); *ppvObject = (void *) ((IUnknown *) this); return S_OK; } else if ( IID_IClassFactory == riid ) { AddRef (); *ppvObject = (void *) ((IClassFactory *) this); return S_OK; } else { *ppvObject = NULL; return E_NOINTERFACE; } } //+--------------------------------------------------------------------------- // // Member: CFilterStatusCF::AddRef // // Synopsis: Increments the reference count on the object // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CFilterStatusCF::AddRef () { return InterlockedIncrement ( (long *)&_cRefs ); } //+--------------------------------------------------------------------------- // // Member: CFilterStatusCF::Release // // Synopsis: Decrements the reference count on the object. // If the reference count reaches 0, the object is deleted. // // History: Jan-13-98 KLam Created // //---------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CFilterStatusCF::Release () { //Win4Assert ( 0 < _cRefs ); unsigned long cTemp = InterlockedDecrement ( (long *)&_cRefs ); if ( 0 == cTemp ) delete this; return cTemp; } //+------------------------------------------------------------------------- // // Method: CFilterStatusCF::CreateInstance // // Synopsis: Create new CFilterStatus instance // // Arguments: [pUnkOuter] -- 'Outer' IUnknown; IGNORED // [riid] -- Interface to bind // [ppvObject] -- Interface returned here // // History: Jan-13-1998 KLam Created // //-------------------------------------------------------------------------- STDMETHODIMP CFilterStatusCF::CreateInstance ( IUnknown * pUnkOuter, REFIID riid, void ** ppvObject ) { if ( 0 != pUnkOuter ) return ResultFromScode ( CLASS_E_NOAGGREGATION ); CFilterStatusDump *pSink = NULL; SCODE sc = S_OK; CTranslateSystemExceptions translate; TRY { // Create a new CFilterStatus pSink = new CFilterStatusDump; // Query the object to see if it supports the desired interface sc = pSink->QueryInterface ( riid, ppvObject ); // Release the class factory's instance of the object pSink->Release (); } CATCH(CException, e) { Win4Assert( 0 == pSink ); sc = GetOleError( e ); } END_CATCH; return sc; } //+------------------------------------------------------------------------- // // Method: CFilterStatusCF::LockServer // // Synopsis: Force class factory to remain loaded // // Arguments: [fLock] -- TRUE to lock ther server. FALSE to unlock the server // // History: Jan-13-1998 KLam Created // //-------------------------------------------------------------------------- STDMETHODIMP CFilterStatusCF::LockServer ( BOOL fLock ) { if ( fLock ) InterlockedIncrement ( &glcInstances ); else InterlockedDecrement ( &glcInstances ); return S_OK; } // // Exported Routines // //+------------------------------------------------------------------------- // // Function: DllGetClassObject // // Synopsis: Ole DLL load class routine // // Arguments: [cid] -- Class to load // [iid] -- Interface to bind to on class object // [ppvObject] -- Interface pointer returned here // // Returns: Text sink dump object // // History: 13-Jan-1998 KLam Created // //-------------------------------------------------------------------------- STDAPI DllGetClassObject( REFCLSID cid, REFIID iid, void ** ppvObject ) { CFilterStatusCF * pFactory = NULL; SCODE sResult = S_OK; CTranslateSystemExceptions translate; TRY { if ( CLSID_CFilterStatusDump == cid ) { pFactory = new CFilterStatusCF; if ( NULL != pFactory ) { sResult = pFactory->QueryInterface( iid, ppvObject ); pFactory->Release ( ); } else sResult = E_OUTOFMEMORY; } else sResult = E_NOINTERFACE; } CATCH(CException, e) { sResult = GetOleError(e); } END_CATCH; return sResult; } //+------------------------------------------------------------------------- // // Method: DllCanUnloadNow // // Synopsis: Queries DLL to see if it can be unloaded // // Returns: S_OK if it is acceptable for caller to unload DLL. // // History: 13-Jan-1998 KLam Created // //-------------------------------------------------------------------------- STDAPI DllCanUnloadNow ( ) { return ( glcInstances <= 0 ) ? S_OK : S_FALSE; } //+------------------------------------------------------------------------- // // Method: DllRegisterServer // // Synopsis: Registers this server with the registry // // Returns: S_OK if registration succeeded, otherwise SELFREG_E_CLASS // // History: 13-Jan-1998 KLam Created // //-------------------------------------------------------------------------- STDAPI DllRegisterServer () { WCHAR const * aKeyValues[4] = { gwszFilterStatusDumpCLSID, gwszDescription, L"InprocServer32", gwszModule }; long retVal = BuildKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) ); if ( ERROR_SUCCESS == retVal ) retVal = AddThreadingModel( L"{3ce7c910-8d72-11d1-8f76-00a0c91917f5}", L"Both" ); if ( ERROR_SUCCESS == retVal ) return S_OK; else return SELFREG_E_CLASS; } //+------------------------------------------------------------------------- // // Method: DllUnregisterServer // // Synopsis: Unregisters this server // // Returns: S_OK if unregistration succeeded, otherwise SELFREG_E_CLASS // // History: 13-Jan-1998 KLam Created // //-------------------------------------------------------------------------- STDAPI DllUnregisterServer () { WCHAR const * aKeyValues[4] = { gwszFilterStatusDumpCLSID, gwszDescription, L"InprocServer32", gwszModule }; long retval = DestroyKeyValues( aKeyValues, sizeof(aKeyValues)/sizeof(aKeyValues[0]) ); if ( ERROR_SUCCESS == retval ) return S_OK; else return SELFREG_E_CLASS; } //+------------------------------------------------------------------------- // // Method: DllMain // // Synopsis: Main routine for DLL. Saves the module name for this dll. // // Returns: TRUE // // History: 13-Jan-1998 KLam Created // //-------------------------------------------------------------------------- BOOL APIENTRY DllMain ( HANDLE hModule, DWORD dwReason, void * pReserved ) { if ( DLL_PROCESS_ATTACH == dwReason ) { DisableThreadLibraryCalls( (HINSTANCE)hModule ); // // Get the name of the module // DWORD dwResult = GetModuleFileName ( (HMODULE)hModule, gwszModule, sizeof(gwszModule)/sizeof(WCHAR) ); //Win4Assert( 0 != dwResult ); } return TRUE; }