|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-2000.
//
// File: Catalog.cxx
//
// Contents: Used to manage catalog(s) state
//
// History: 27-Nov-1996 KyleP Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <params.hxx>
#include <ciregkey.hxx>
#include <snapin.hxx>
#include <catalog.hxx>
#include <catadmin.hxx>
#include <CIARes.h>
#include <callback.hxx>
#include <fsciexps.hxx>
CDynArrayInPlace<CCatalogs *> gapCats; CDynArrayInPlace<UINT_PTR> gaTimerIds; UINT gsIndex = 0; UINT gcMaxCats = 0; CStaticMutexSem gmtxTimer; const cRefreshDelay = 5000;
//
// Global data
//
SCatalogColumn coldefCatalog[] = { { CCatalog::GetCat, MSG_COL_CATNAME }, { CCatalog::GetDrive, MSG_COL_DRIVE }, { CCatalog::GetSize, MSG_COL_SIZE }, { CCatalog::GetDocs, MSG_COL_DOCTOTAL }, { CCatalog::GetDocsToFilter, MSG_COL_DOCFILTER }, { CCatalog::GetSecQDocuments, MSG_COL_SECQDOCUMENTS }, { CCatalog::GetWordlists, MSG_COL_WORDLISTS }, { CCatalog::GetPersIndex, MSG_COL_PERSINDEX }, { CCatalog::GetStatus, MSG_COL_STATUS } };
const unsigned cColDefCatalog = sizeof(coldefCatalog) / sizeof(coldefCatalog[0]);
//
// Static command tree to fetch property metadata.
//
// NOTE: There are some funny casts below, because of the requirement to
// statically initialize a union.
//
const DBID dbcolGuid = { { 0x624c9360, 0x93d0, 0x11cf, 0xa7, 0x87, 0x00, 0x00, 0x4c, 0x75, 0x27, 0x52 }, DBKIND_GUID_PROPID, (LPWSTR)5 };
const DBID dbcolPropDispid = { { 0x624c9360, 0x93d0, 0x11cf, 0xa7, 0x87, 0x00, 0x00, 0x4c, 0x75, 0x27, 0x52 }, DBKIND_GUID_PROPID, (LPWSTR)6 };
const DBID dbcolPropName = { { 0x624c9360, 0x93d0, 0x11cf, 0xa7, 0x87, 0x00, 0x00, 0x4c, 0x75, 0x27, 0x52 }, DBKIND_GUID_PROPID, (LPWSTR)7 };
const DBID dbcolPropLevel = { { 0x624c9360, 0x93d0, 0x11cf, 0xa7, 0x87, 0x00, 0x00, 0x4c, 0x75, 0x27, 0x52 }, DBKIND_GUID_PROPID, (LPWSTR)8 };
const DBID dbcolPropDataModifiable = { { 0x624c9360, 0x93d0, 0x11cf, 0xa7, 0x87, 0x00, 0x00, 0x4c, 0x75, 0x27, 0x52 }, DBKIND_GUID_PROPID, (LPWSTR)9 };
const DBID dbcolPropType = { { 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac }, DBKIND_GUID_PROPID, (LPWSTR)4 };
const DBID dbcolSize = { { 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac }, DBKIND_GUID_PROPID, (LPWSTR)12 };
const DBID dbcolPath = { { 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac }, DBKIND_GUID_PROPID, (LPWSTR)11 };
//
// This is just like PROPVARIANT, but w/o all the arms. Lets you statically
// assign a VT_CLSID.
//
struct tag_Kyle_PROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; CLSID __RPC_FAR *puuid; };
GUID psguidStorage = PSGUID_STORAGE; tag_Kyle_PROPVARIANT stVar = { VT_CLSID, 0, 0, 0, &psguidStorage }; //CStorageVariant stVar((CLSID *)&psguidStorage);
//
// Columns
//
DBCOMMANDTREE dbcmdColumnPath = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPath, S_OK }; DBCOMMANDTREE dbcmdColumnGuid = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolGuid, S_OK }; DBCOMMANDTREE dbcmdColumnPropDispid = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPropDispid, S_OK }; DBCOMMANDTREE dbcmdColumnPropName = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPropName, S_OK }; DBCOMMANDTREE dbcmdColumnPropType = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPropType, S_OK }; DBCOMMANDTREE dbcmdColumnSize = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolSize, S_OK }; DBCOMMANDTREE dbcmdColumnStoreLevel = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPropLevel, S_OK }; DBCOMMANDTREE dbcmdColumnModifiable = { DBOP_column_name, DBVALUEKIND_ID, 0, 0, (ULONG_PTR)&dbcolPropDataModifiable, S_OK };
//
// Forward declare a few nodes to make linking easy
//
extern DBCOMMANDTREE dbcmdSortListAnchor; extern DBCOMMANDTREE dbcmdProjectListAnchor;
//
// Select NOT (guid == PSGUID_STORAGE AND dispid == 19) ; everything but CONTENTS property
//
// the guid == psguid_storage clause
DBCOMMANDTREE dbcmdGuidStorage = { DBOP_scalar_constant, DBVALUEKIND_VARIANT, 0, 0, (ULONG_PTR)&stVar, S_OK };
DBCOMMANDTREE dbcmdColumnGuid2 = { DBOP_column_name, DBVALUEKIND_ID, 0, &dbcmdGuidStorage, (ULONG_PTR)&dbcolGuid, S_OK };
DBCOMMANDTREE dbcmdEqual = { DBOP_equal, DBVALUEKIND_I4, &dbcmdColumnGuid2, 0, 0, S_OK };
// the dispid == 19 clause
DBCOMMANDTREE dbcmdContentsId = { DBOP_scalar_constant, DBVALUEKIND_UI4, 0, 0, 19, S_OK };
DBCOMMANDTREE dbcmdColumnDispid = { DBOP_column_name, DBVALUEKIND_ID, 0, &dbcmdContentsId, (ULONG_PTR)&dbcolPropDispid, S_OK };
DBCOMMANDTREE dbcmdEqual2 = { DBOP_equal, DBVALUEKIND_I4, &dbcmdColumnDispid, &dbcmdEqual, 0, S_OK };
// the and node between the above two clauses
DBCOMMANDTREE dbcmdAnd = { DBOP_and, DBVALUEKIND_I4, &dbcmdEqual2, 0, 0, S_OK };
// the not in front of the above node
DBCOMMANDTREE dbcmdNot = { DBOP_not, DBVALUEKIND_I4, &dbcmdAnd, 0, 0, S_OK };
WCHAR wszTable[] = L"Table";
DBCOMMANDTREE dbcmdTable = { DBOP_table_name, DBVALUEKIND_WSTR, 0, &dbcmdNot, (ULONG_PTR)&wszTable[0], S_OK };
DBCOMMANDTREE dbcmdSelect = { DBOP_select, DBVALUEKIND_EMPTY, &dbcmdTable, &dbcmdProjectListAnchor, 0, S_OK };
//
// Project (Path, GUID, ...)
//
// NOTE: The order here defines the ordinals of columns.
// The first one here is the last entry in the
// column list, as it is the last child in the
// projection list command tree.
//
DBCOMMANDTREE dbcmdProjectModifiable = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnModifiable, 0, 0, S_OK };
DBCOMMANDTREE dbcmdProjectStoreLevel = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnStoreLevel, &dbcmdProjectModifiable, 0, S_OK };
DBCOMMANDTREE dbcmdProjectSize = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnSize, &dbcmdProjectStoreLevel, 0, S_OK };
DBCOMMANDTREE dbcmdProjectPropType = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnPropType, &dbcmdProjectSize, 0, S_OK };
DBCOMMANDTREE dbcmdProjectPropName = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnPropName, &dbcmdProjectPropType, 0, S_OK };
DBCOMMANDTREE dbcmdProjectPropDispid = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnPropDispid, &dbcmdProjectPropName, 0, S_OK };
DBCOMMANDTREE dbcmdProjectGuid = { DBOP_project_list_element, DBVALUEKIND_EMPTY, &dbcmdColumnGuid, &dbcmdProjectPropDispid, 0, S_OK };
DBCOMMANDTREE dbcmdProjectListAnchor = { DBOP_project_list_anchor, DBVALUEKIND_EMPTY, &dbcmdProjectGuid, 0, 0, S_OK };
DBCOMMANDTREE dbcmdProject = { DBOP_project, DBVALUEKIND_EMPTY, &dbcmdSelect, &dbcmdSortListAnchor, 0, S_OK };
//
// Sort (Ascending by GUID)
//
DBSORTINFO dbsortAscending = { FALSE, LOCALE_NEUTRAL };
DBCOMMANDTREE dbcmdSortByGuid = { DBOP_sort_list_element, DBVALUEKIND_SORTINFO, &dbcmdColumnGuid, 0, (ULONG_PTR)&dbsortAscending, S_OK };
DBCOMMANDTREE dbcmdSortListAnchor = { DBOP_sort_list_anchor, DBVALUEKIND_EMPTY, &dbcmdSortByGuid, 0, 0, S_OK };
DBCOMMANDTREE dbcmdSort = { DBOP_sort, DBVALUEKIND_EMPTY, &dbcmdProject, 0, 0, S_OK };
//
// Static set of bindings for fetching property info.
//
struct SPropInfo { GUID guidPropertySet; PROPID propid; ULONG statusPropid; WCHAR * pwcsName; ULONG statusName; ULONG type; ULONGLONG size; DWORD level; VARIANT_BOOL fModifiable; };
DBBINDING abindPropInfo[] = { { 1, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->guidPropertySet, // Value offset
0, // Length offset
0, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->guidPropertySet ),// Value length
0, // Flags
VT_CLSID, // Datatype expected
0, // Precision (unused)
0 }, // Scale (unused)
{ 2, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->propid, // Value offset
0, // Length offset
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->statusPropid, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE | DBPART_STATUS, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->propid ), // Value length
0, // Flags
DBTYPE_I4, // Datatype expected
0, // Precision (unused)
0 }, // Scale (unused)
{ 3, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->pwcsName, // Value offset
0, // Length offset
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->statusName, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE | DBPART_STATUS, // Fetch value
DBMEMOWNER_PROVIDEROWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->pwcsName ), // Value length
0, // Flags
DBTYPE_WSTR | DBTYPE_BYREF, // Datatype expected
0, // Precision (unused)
0 }, // Scale (unused)
{ 4, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->type, // Value offset
0, // Length offset
0, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->type ), // Value length
0, // Flags
DBTYPE_UI4, // Datatype expected
0, // Precision (unused)
0 }, // Scale (unused)
{ 5, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->size, // Value offset
0, // Length offset
0, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->size ), // Value length
0, // Flags
DBTYPE_I8, // Datatype expected
0, // Precision (unused)
0 }, // Scale (unused)
{ 6, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->level, // Value offset
0, // Length offset
0, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->level ), // Value length
0, // Flags
DBTYPE_UI4, // Datatype expected
0, // Precision (unused)
0 },
{ 7, // Ordinal
(ULONG) (ULONG_PTR)&((SPropInfo *)0)->fModifiable, // Value offset
0, // Length offset
0, // Status offset
0, // Typeinfo
0, // Object
0, // BindExt
DBPART_VALUE, // Fetch value
DBMEMOWNER_CLIENTOWNED, // Client owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
sizeof( ((SPropInfo *)0)->fModifiable ), // Value length
0, // Flags
DBTYPE_BOOL, // Datatype expected
0, // Precision (unused)
0 }};
BOOL CCatalogs::_fFirstTime = TRUE;
CCatalog::CCatalog( CCatalogs & parent, WCHAR const * pwcsCat ) : _idScope( 0 ), _idResult( 0 ), _pwcsDrive( 0 ), _pwcsCat( 0 ), _parent( parent ), _fZombie( FALSE ), #pragma warning( disable : 4355 ) // this used in base initialization
_interScopes( *this, Intermediate_Scope ), _interProperties( *this, Intermediate_Properties ), _interUnfiltered( *this, Intermediate_UnfilteredURL ) #pragma warning( default : 4355 )
{ //
// Hack Alert! This will fake ::Update into thinking all the values need to be
// changed.
//
RtlFillMemory( &_state, sizeof(_state), 0xAA ); _state.cbStruct = sizeof(_state);
TRY { //
// Initialize string(s)
//
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( pwcsCat ) );
Set( xCatalogAdmin->GetLocation(), _pwcsDrive ); Set( pwcsCat, _pwcsCat ); _fInactive = xCatalogAdmin->IsCatalogInactive();
Update();
//
// Make sure we think the orignal value is new
//
_fSizeChanged = TRUE; _fPropCacheSizeChanged = TRUE; _fDocsChanged = TRUE; _fDocsToFilterChanged = TRUE; _fWordlistsChanged = TRUE; _fPersIndexChanged = TRUE; _fStatusChanged = TRUE; _fSecQDocumentsChanged = TRUE;
} CATCH( CException, e ) { delete [] _pwcsDrive; delete [] _pwcsCat;
RETHROW(); } END_CATCH }
void CCatalog::InitScopeHeader( CListViewHeader & Header ) { CScope::InitHeader( Header ); }
void CCatalog::InitPropertyHeader( CListViewHeader & Header ) { CCachedProperty::InitHeader( Header ); }
CCatalog::~CCatalog() { delete [] _pwcsDrive; delete [] _pwcsCat; }
SCODE CCatalog::AddScope( WCHAR const * pwszScope, WCHAR const * pwszAlias, BOOL fExclude, WCHAR const * pwszLogon, WCHAR const * pwszPassword ) { ciaDebugOut(( DEB_ITRACE, "CCatalog::AddScope( %ws, %ws, %s, %ws, %ws )\n", pwszScope, (0 == pwszAlias) ? L"" : pwszAlias, fExclude ? "TRUE" : "FALSE", (0 == pwszLogon) ? L"n/a" : pwszLogon, (0 == pwszPassword) ? L"n/a" : pwszPassword ));
SCODE sc = S_OK; TRY { //
// First, add to CI.
//
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); xCatalogAdmin->AddScope( pwszScope, pwszAlias, fExclude, pwszLogon, pwszPassword ); } CATCH (CException, e) { sc = e.GetErrorCode(); } END_CATCH
return (FAILED(sc) ? sc : S_OK); }
void CCatalog::RemoveScope( CScope * pScope ) { SCODE sc = S_OK;
TRY { //
// First, remove from CI.
//
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
xCatalogAdmin->RemoveScope( pScope->GetPath() ); } CATCH (CException, e) { sc = e.GetErrorCode(); } END_CATCH
if (FAILED(sc)) { // At this point nothing was removed from the registry, so we shouldn't zombify the scope.
return; }
//
// Then, from display.
//
pScope->Zombify(); }
SCODE CCatalog::ModifyScope( CScope & rScope, WCHAR const * pwszScope, WCHAR const * pwszAlias, BOOL fExclude, WCHAR const * pwszLogon, WCHAR const * pwszPassword ) { ciaDebugOut(( DEB_ITRACE, "CCatalog::ModifyScope( %ws, %ws, %s, %ws, %ws )\n", pwszScope, (0 == pwszAlias) ? L"" : pwszAlias, fExclude ? "TRUE" : "FALSE", (0 == pwszLogon) ? L"n/a" : pwszLogon, (0 == pwszPassword) ? L"n/a" : pwszPassword ));
SCODE sc = S_OK;
TRY { //
// First, remove from CI.
//
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
//
// If the path hasn't changed, we should only change properties that have
// changed. If the path has changed, it will cause the value to be deleted
// anyway, so we can remove the scope and add the replacement in one shot.
//
if (0 == _wcsicmp(rScope.GetPath(), pwszScope)) { XPtr<CScopeAdmin> xScopeAdmin( xCatalogAdmin->QueryScopeAdmin(rScope.GetPath()) );
xScopeAdmin->SetAlias(pwszAlias);
xScopeAdmin->SetExclude(fExclude);
xScopeAdmin->SetLogonInfo(pwszLogon, pwszPassword, xCatalogAdmin.GetReference()); } else { xCatalogAdmin->RemoveScope( rScope.GetPath() ); // Then add the entry to CI
xCatalogAdmin->AddScope( pwszScope, pwszAlias, fExclude, pwszLogon, pwszPassword ); }
// Then modify the display entry in place
rScope.Modify( pwszScope, pwszAlias, fExclude ); } CATCH (CException, e) { sc = e.GetErrorCode(); } END_CATCH
return sc; }
void CCatalog::RescanScope( WCHAR const * pwszScope, BOOL fFull ) { SCODE sc = UpdateContentIndex ( pwszScope, _pwcsCat, _parent.GetMachine(), fFull );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "UpdateContentIndex( %ws ) returned 0x%x\n", pwszScope, sc ));
THROW( CException( sc ) ); } }
void CCatalog::Merge() { SCODE sc = ForceMasterMerge ( L"\\", _pwcsCat, _parent.GetMachine() );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "ForceMasterMerge( %ws ) returned 0x%x\n", _pwcsCat, sc ));
THROW( CException( sc ) ); } }
void CCatalog::DisplayIntermediate( IConsoleNameSpace * pScopePane ) { //
// Now, insert the intermediate nodes.
//
SCOPEDATAITEM item;
RtlZeroMemory( &item, sizeof(item) );
//
// 'Scope'
//
item.mask |= SDI_STR | SDI_IMAGE | SDI_CHILDREN; item.nImage = ICON_FOLDER; //item.displayname = (WCHAR *)pCat->GetCat( TRUE );
item.displayname = MMC_CALLBACK; item.cChildren = 0;
item.mask |= SDI_PARAM; item.lParam = (LPARAM)GetIntermediateScopeNode();
item.relativeID = ScopeHandle();
ciaDebugOut(( DEB_ITRACE, "Inserting (intermediate) scope item (lParam = 0x%x)\n", item.lParam ));
pScopePane->InsertItem( &item );
//
// 'Properties'
//
item.mask |= SDI_STR | SDI_IMAGE | SDI_CHILDREN; item.nImage = ICON_FOLDER; //item.displayname = (WCHAR *)pCat->GetCat( TRUE );
item.displayname = MMC_CALLBACK; item.cChildren = 0;
item.mask |= SDI_PARAM; item.lParam = (LPARAM)GetIntermediatePropNode();
item.relativeID = ScopeHandle();
ciaDebugOut(( DEB_ITRACE, "Inserting (intermediate) property item (lParam = 0x%x)\n", item.lParam ));
pScopePane->InsertItem( &item );
//
// Unfiltered query URL
//
item.mask |= SDI_STR | SDI_IMAGE | SDI_OPENIMAGE | SDI_CHILDREN; item.nImage = item.nOpenImage = ICON_URL; item.displayname = MMC_CALLBACK; item.cChildren = 0;
item.mask |= SDI_PARAM; item.lParam = (LPARAM)GetIntermediateUnfilteredNode();
item.relativeID = ScopeHandle();
ciaDebugOut(( DEB_ITRACE, "Inserting (intermediate) URL item (lParam = 0x%x)\n", item.lParam ));
pScopePane->InsertItem( &item ); }
void CCatalog::DisplayScopes( BOOL fFirstTime, IResultData * pResultPane ) { ciaDebugOut(( DEB_ITRACE, "CCatalog::DisplayScopes (fFirstTime = %d)\n", fFirstTime ));
ClearScopes(pResultPane); PopulateScopes();
for ( unsigned i = 0; i < _aScope.Count(); i++ ) { CScope * pScope = _aScope.Get( i );
Win4Assert(!pScope->IsZombie());
//
// All items were freshly enumerated. add them all
//
RESULTDATAITEM item; RtlZeroMemory( &item, sizeof(item) );
item.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; item.nCol = 0;
// item.nImage will be set by ::GetDisplayInfo
pScope->GetDisplayInfo( &item );
item.str = MMC_CALLBACK; item.lParam = (LPARAM)pScope;
ciaDebugOut(( DEB_ITRACE, "Inserting result item %ws (lParam = 0x%x)\n", pScope->GetPath(), item.lParam ));
pResultPane->InsertItem( &item );
pScope->SetResultHandle( item.itemID ); } }
void CCatalog::ClearProperties(IResultData * pResultPane) { // Clear out the display list
pResultPane->DeleteAllRsltItems();
// Delete the entries from the property list
_aProperty.Clear(); }
void CCatalog::DisplayProperties( BOOL fFirstTime, IResultData * pResultPane ) { ciaDebugOut(( DEB_ITRACE, "CCatalog::DisplayProperties (fFirstTime = %d)\n", fFirstTime ));
// If catalog is stopped OR service is stopped, clear the list.
BOOL fStopped = FALSE; TRY { CMachineAdmin MachineAdmin( _parent.IsLocalMachine() ? 0 : _parent.GetMachine() );
XPtr<CCatalogAdmin> xCat( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
fStopped = xCat->IsStopped() || MachineAdmin.IsCIStopped();
if (fStopped) ClearProperties(pResultPane); } CATCH( CException, e) { // nothing to do
} END_CATCH
if (fStopped) return;
if ( fFirstTime ) UpdateProps();
for ( unsigned i = 0; i < _aProperty.Count(); i++ ) { CCachedProperty * pProperty = _aProperty.Get( i );
if ( pProperty->IsZombie() ) { pResultPane->DeleteItem( pProperty->ResultHandle(), 0 );
//
// Delete scope and move highest entry down.
//
pProperty = _aProperty.Acquire( i ); delete pProperty;
if ( _aProperty.Count() > 0 && _aProperty.Count() != i ) { pProperty = _aProperty.Acquire( _aProperty.Count() - 1 ); _aProperty.Add( pProperty, i ); }
continue; }
if ( fFirstTime || pProperty->IsNew() ) { //
// Add item
//
RESULTDATAITEM item; RtlZeroMemory( &item, sizeof(item) );
item.mask = RDI_STR | RDI_IMAGE | RDI_PARAM; item.nCol = 0;
pProperty->GetDisplayInfo( &item ); // item.nImage is set from ::GetDisplayInfo
item.str = MMC_CALLBACK; item.lParam = (LPARAM)pProperty;
ciaDebugOut(( DEB_ITRACE, "Inserting result item %ws (lParam = 0x%x)\n", pProperty->GetProperty(), item.lParam ));
pResultPane->InsertItem( &item );
pProperty->SetResultHandle( item.itemID ); pProperty->MakeOld(); }
if ( !fFirstTime && !pProperty->IsNew() ) { if ( !pProperty->IsUnappliedChange() ) { //
// Set the icon back to normal.
//
RESULTDATAITEM rdi; RtlZeroMemory(&rdi, sizeof(rdi));
rdi.mask = RDI_IMAGE; rdi.itemID = pProperty->ResultHandle();
// item.nImage is set from ::GetDisplayInfo
pProperty->GetDisplayInfo( &rdi );
SCODE sc = pResultPane->SetItem( &rdi ); } } } }
void CCatalog::GetGeneration( BOOL & fFilterUnknown, BOOL & fGenerateCharacterization, ULONG & ccCharacterization ) { // Caller will deal with exceptions.
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
DWORD dw;
//
// Filter Unknown
//
if ( !xCatalogAdmin->GetDWORDParam( wcsFilterFilesWithUnknownExtensions, dw ) && !MachineAdmin.GetDWORDParam( wcsFilterFilesWithUnknownExtensions, dw ) ) dw = CI_FILTER_FILES_WITH_UNKNOWN_EXTENSIONS_DEFAULT;
fFilterUnknown = (0 != dw);
//
// Characterization. We should check if generatecharacterization flag is set to
// TRUE and also check the characterization size. Only when the flag is set to TRUE
// and size > 0, should we generate characterization.
//
DWORD dwGenCharacterization = 0;
if ( !xCatalogAdmin->GetDWORDParam( wcsGenerateCharacterization, dwGenCharacterization ) && !MachineAdmin.GetDWORDParam( wcsGenerateCharacterization, dwGenCharacterization ) ) dwGenCharacterization = 1;
if ( !xCatalogAdmin->GetDWORDParam( wcsMaxCharacterization, ccCharacterization ) && !MachineAdmin.GetDWORDParam( wcsMaxCharacterization, ccCharacterization ) ) ccCharacterization = CI_MAX_CHARACTERIZATION_DEFAULT;
fGenerateCharacterization = (ccCharacterization > 0) && (0 != dwGenCharacterization); }
void CCatalog::SetGeneration( BOOL fFilterUnknown, BOOL fGenerateCharacterization, ULONG ccCharacterization ) { //
// fGenerateCharacterization is obsolete.
//
if ( !fGenerateCharacterization ) ccCharacterization = 0;
// Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
xCatalogAdmin->SetDWORDParam( wcsFilterFilesWithUnknownExtensions, fFilterUnknown ); xCatalogAdmin->SetDWORDParam( wcsGenerateCharacterization, fGenerateCharacterization ); xCatalogAdmin->SetDWORDParam( wcsMaxCharacterization, ccCharacterization ); }
void CCatalog::GetTracking( BOOL & fAutoAlias ) { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
DWORD dw;
if ( !xCatalogAdmin->GetDWORDParam( wcsIsAutoAlias, dw ) && !MachineAdmin.GetDWORDParam( wcsIsAutoAlias, dw ) ) dw = CI_IS_AUTO_ALIAS_DEFAULT;
fAutoAlias = (0 != dw); }
void CCatalog::SetTracking( BOOL fAutoAlias ) { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
xCatalogAdmin->SetDWORDParam( wcsIsAutoAlias, fAutoAlias ); }
void CCatalog::GetWeb( BOOL & fVirtualRoots, BOOL & fNNTPRoots, ULONG & iVirtualServer, ULONG & iNNTPServer ) { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
DWORD dw;
//
// Filter Virtual Roots
//
if ( !xCatalogAdmin->GetDWORDParam( wcsIsIndexingW3Roots, dw ) && !MachineAdmin.GetDWORDParam( wcsIsIndexingW3Roots, dw ) ) dw = CI_IS_INDEXING_W3_ROOTS_DEFAULT;
fVirtualRoots = (0 != dw);
//
// Filter NNTP Roots
//
if ( !xCatalogAdmin->GetDWORDParam( wcsIsIndexingNNTPRoots, dw ) && !MachineAdmin.GetDWORDParam( wcsIsIndexingNNTPRoots, dw ) ) dw = CI_IS_INDEXING_NNTP_ROOTS_DEFAULT;
fNNTPRoots = (0 != dw);
//
// Virtual server
//
if ( !xCatalogAdmin->GetDWORDParam( wcsW3SvcInstance, iVirtualServer ) && !MachineAdmin.GetDWORDParam( wcsW3SvcInstance, iVirtualServer ) ) iVirtualServer = CI_W3SVC_INSTANCE_DEFAULT;
//
// NNTP Virtual server
//
if ( !xCatalogAdmin->GetDWORDParam( wcsNNTPSvcInstance, iNNTPServer ) && !MachineAdmin.GetDWORDParam( wcsNNTPSvcInstance, iNNTPServer ) ) iNNTPServer = CI_NNTPSVC_INSTANCE_DEFAULT; }
void CCatalog::SetWeb( BOOL fVirtualRoots, BOOL fNNTPRoots, ULONG iVirtualServer, ULONG iNNTPServer ) { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
xCatalogAdmin->SetDWORDParam( wcsIsIndexingW3Roots, fVirtualRoots ); xCatalogAdmin->SetDWORDParam( wcsIsIndexingNNTPRoots, fNNTPRoots ); xCatalogAdmin->SetDWORDParam( wcsW3SvcInstance, iVirtualServer ); xCatalogAdmin->SetDWORDParam( wcsNNTPSvcInstance, iNNTPServer ); }
void CCatalog::UpdateCachedProperty(CCachedProperty *pProperty) { TRY { CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin(GetCat(TRUE)) );
Win4Assert(pProperty->IsUnappliedChange() );
xCatalogAdmin->AddCachedProperty( *((CFullPropSpec const *)pProperty->GetFullPropspec()), pProperty->GetVT(), pProperty->Allocation(), pProperty->StoreLevel(), pProperty->IsModifiable());
pProperty->ClearUnappliedChange(); } CATCH(CException, e) { ULONG cc = wcslen(pProperty->GetPropSet()); cc++; cc += wcslen(pProperty->GetProperty()); cc++;
XGrowable<WCHAR> xPropDescription(cc);
wcscpy(xPropDescription.Get(), pProperty->GetPropSet()); wcscat(xPropDescription.Get(), L" "); wcscat(xPropDescription.Get(), pProperty->GetProperty());
MessageBox(GetFocus(), xPropDescription.Get(), STRINGRESOURCE( srPropCommitErrorT ), MB_ICONWARNING);
} END_CATCH }
void CCatalog::Set( WCHAR const * pwcsSrc, WCHAR * & pwcsDst ) { if ( 0 == pwcsSrc ) { pwcsDst = new WCHAR[2]; RtlCopyMemory( pwcsDst, L" ", 2*sizeof(WCHAR) ); } else { unsigned cc = wcslen( pwcsSrc ) + 1;
pwcsDst = new WCHAR [cc];
RtlCopyMemory( pwcsDst, pwcsSrc, cc * sizeof(WCHAR) ); } }
void CCatalog::Stringize( DWORD dwValue, WCHAR * pwcsDst, unsigned ccDst ) { //
// GetNumberFormat places additional decimals at the end...
//
#if 0
WCHAR wcTemp[100];
_ultow( dwValue, wcTemp, 10 ); GetNumberFormat( LOCALE_USER_DEFAULT, // Default locale
0, // Flags
wcTemp, // Input
0, // More formatting info
pwcsDst, // Output buffer
ccDst ); // Size
#else
_ultow( dwValue, pwcsDst, 10 ); #endif
}
BOOL CCatalog::Update() { //
// Get state
//
CI_STATE state; ULONG ulCacheSizeInKB;
state.cbStruct = sizeof(state);
SCODE sc = CIState( _pwcsCat, _parent.GetMachine(), &state );
if ( FAILED(sc) ) { Null( _awcWordlists ); Null( _awcPersIndex ); Null( _awcSize ); Null( _awcPropCacheSize ); Null( _awcDocsToFilter ); Null( _awcSecQDocuments ); Null( _awcDocs ); Null( _awcStatus );
//
// Make sure when we come back to life we will update values.
//
RtlFillMemory( &_state, sizeof(_state), 0xAA ); _state.cbStruct = sizeof(_state);
_fSizeChanged = TRUE; _fPropCacheSizeChanged = TRUE; _fDocsChanged = TRUE; _fDocsToFilterChanged = TRUE; _fWordlistsChanged = TRUE; _fPersIndexChanged = TRUE; _fStatusChanged = TRUE; _fSecQDocumentsChanged = TRUE;
TRY { CMachineAdmin MachineAdmin( _parent.IsLocalMachine() ? 0 : _parent.GetMachine() );
XPtr<CCatalogAdmin> xCat( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) );
if (xCat->IsStopped()) { wcscpy( _awcStatus, STRINGRESOURCE(srStopped) ); } } CATCH( CException, e) { // nothing to do
} END_CATCH } else { //
// String-ize
//
//
// Could put more of this in a method, but it seems like overkill. A table based
// solution will be necessary if this list grows.
//
if ( _state.cWordList != state.cWordList ) { Stringize( state.cWordList, _awcWordlists, sizeof(_awcWordlists)/sizeof(WCHAR) ); _fWordlistsChanged = TRUE; } else _fWordlistsChanged = FALSE;
if ( _state.cPersistentIndex != state.cPersistentIndex ) { Stringize( state.cPersistentIndex, _awcPersIndex, sizeof(_awcPersIndex)/sizeof(WCHAR) ); _fPersIndexChanged = TRUE; } else _fPersIndexChanged = FALSE;
if ( _state.dwIndexSize != state.dwIndexSize ) { Stringize( state.dwIndexSize, _awcSize, sizeof(_awcSize)/sizeof(WCHAR) ); _fSizeChanged = TRUE; } else _fSizeChanged = FALSE;
if (_state.dwPropCacheSize != state.dwPropCacheSize) { Stringize(state.dwPropCacheSize/1024, _awcPropCacheSize, sizeof(_awcPropCacheSize)/sizeof(WCHAR)); _fPropCacheSizeChanged = TRUE; } else _fPropCacheSizeChanged = FALSE;
if ( _state.cDocuments != state.cDocuments ) { Stringize( state.cDocuments, _awcDocsToFilter, sizeof(_awcDocsToFilter)/sizeof(WCHAR) ); _fDocsToFilterChanged = TRUE; } else _fDocsToFilterChanged = FALSE;
if ( _state.cSecQDocuments != state.cSecQDocuments ) { Stringize( state.cSecQDocuments, _awcSecQDocuments, sizeof(_awcSecQDocuments)/sizeof(WCHAR) ); _fSecQDocumentsChanged = TRUE; } else _fSecQDocumentsChanged = FALSE;
if ( _state.cTotalDocuments != state.cTotalDocuments ) { Stringize( state.cTotalDocuments, _awcDocs, sizeof(_awcDocs)/sizeof(WCHAR) ); _fDocsChanged = TRUE; } else _fDocsChanged = FALSE;
if ( _state.eState != state.eState || _state.dwMergeProgress != state.dwMergeProgress ) { FormatStatus( state ); _fStatusChanged = TRUE; } else _fStatusChanged = FALSE;
RtlCopyMemory( &_state, &state, sizeof(state) ); }
return ChangesPending(); }
BOOL CCatalog::UpdateProps() { if ( 0 != _aProperty.Count() ) return FALSE;
//
// Look for cached properties
//
IUnknown * pIUnknown; XInterface<ICommand> xCmd;
SCODE sc = MakeMetadataICommand( &pIUnknown, CiProperties, _pwcsCat, _parent.GetMachine() ); if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x creating metadata ICommand\n", sc ));
//THROW( CException(sc) );
return FALSE; }
XInterface<IUnknown> xUnk( pIUnknown ); sc = pIUnknown->QueryInterface(IID_ICommand, xCmd.GetQIPointer());
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x on QueryInterface IID_ICommand\n", sc ));
//THROW( CException(sc) );
return FALSE; }
XInterface<ICommandTree> xCmdTree;
sc = xCmd->QueryInterface( IID_ICommandTree, xCmdTree.GetQIPointer() );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x binding to ICommandTree\n", sc ));
//THROW( CException(sc) );
return FALSE; }
DBCOMMANDTREE * pTree = &dbcmdSort;
sc = xCmdTree->SetCommandTree( &pTree, DBCOMMANDREUSE_NONE, TRUE );
Win4Assert( 0 != pTree ); // Make sure it wasn't taken from us!
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x setting command tree\n", sc ));
//THROW( CException(sc) );
return FALSE; }
XInterface<IRowset> xRowset;
sc = xCmd->Execute( 0, IID_IRowset, 0, 0, (IUnknown **)xRowset.GetQIPointer() );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x creating metadata rowset.\n", sc ));
//THROW( CException(sc) );
return FALSE; }
//
// Now, we have a cursor. Create some bindings. Below this point, we shouldn't
// expect any errors.
//
XInterface<IAccessor> xAccessor;
sc = xRowset->QueryInterface( IID_IAccessor, xAccessor.GetQIPointer() );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x binding to IAccessor\n", sc )); THROW( CException(sc) ); }
HACCESSOR hacc;
sc = xAccessor->CreateAccessor( DBACCESSOR_ROWDATA, sizeof(abindPropInfo) / sizeof(abindPropInfo[0]), abindPropInfo, 0, &hacc, 0 );
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Error 0x%x binding to IAccessor\n", sc )); THROW( CException(sc) ); }
//
// Now we have a cursor and bindings. Iterate over the data.
//
while ( SUCCEEDED(sc) && sc != DB_S_ENDOFROWSET ) { HROW ahrow[10]; DBCOUNTITEM cRow; HROW* phrow = ahrow;
sc = xRowset->GetNextRows( 0, // Chapter
0, // Skip
sizeof(ahrow)/sizeof(ahrow[0]), // Count requested
&cRow, // Count fetched
&phrow );
if ( SUCCEEDED(sc) ) { for ( ULONG i = 0; SUCCEEDED(sc) && i < cRow; i++ ) { SPropInfo sprop;
sc = xRowset->GetData( ahrow[i], hacc, &sprop );
Win4Assert( DBSTATUS_S_OK == sprop.statusPropid || DBSTATUS_S_OK == sprop.statusName );
if ( SUCCEEDED(sc) && ( DBSTATUS_S_OK == sprop.statusPropid || DBSTATUS_S_OK == sprop.statusName ) ) { PROPSPEC ps = { PRSPEC_PROPID, 1 };
if ( DBSTATUS_S_OK == sprop.statusName ) { ps.ulKind = PRSPEC_LPWSTR; ps.lpwstr = sprop.pwcsName; } else ps.propid = sprop.propid;
CCachedProperty * pProp = new CCachedProperty( *this, sprop.guidPropertySet, ps, sprop.type, sprop.size, sprop.level, sprop.fModifiable );
_aProperty.Add( pProp, _aProperty.Count() ); } }
if ( FAILED(sc) || sc == DB_S_ENDOFROWSET ) xRowset->ReleaseRows( cRow, ahrow, 0, 0, 0 ); else sc = xRowset->ReleaseRows( cRow, ahrow, 0, 0, 0 ); } }
if ( FAILED(sc) ) { ciaDebugOut(( DEB_ERROR, "Something bad during row fetch (0x%x)\n", sc )); THROW( CException(sc) ); }
xAccessor->ReleaseAccessor( hacc, 0 );
return TRUE; }
void CCatalog::FormatStatus( CI_STATE & state ) { //
// One-shot initialization
//
static unsigned ccScanReq; static unsigned ccScanning; static unsigned ccRecovering; static unsigned ccMMPaused; static unsigned ccHighIo; static unsigned ccLowMemory; static unsigned ccReadOnly; static unsigned ccBattery; static unsigned ccUserActive; static unsigned ccStarting; static unsigned ccReadingUsns; static unsigned ccStarted;
if ( 0 == ccScanReq ) { ccScanReq = wcslen( STRINGRESOURCE( srScanReq ) ); ccScanning = wcslen( STRINGRESOURCE( srScanning ) ); ccRecovering = wcslen( STRINGRESOURCE( srRecovering ) ); ccMMPaused = wcslen( STRINGRESOURCE( srMMPaused ) ); ccHighIo = wcslen( STRINGRESOURCE( srHighIo ) ); ccLowMemory = wcslen( STRINGRESOURCE( srLowMemory ) ); ccReadOnly = wcslen( STRINGRESOURCE( srReadOnly ) ); ccBattery = wcslen( STRINGRESOURCE( srBattery ) ); ccUserActive = wcslen( STRINGRESOURCE( srUserActive ) ); ccStarting = wcslen( STRINGRESOURCE( srStarting ) ); ccReadingUsns = wcslen( STRINGRESOURCE( srReadingUsns ) ); ccStarted = wcslen( STRINGRESOURCE( srStarted ) ); }
_awcStatus[0] = 0;
WCHAR * pwcsStatus = _awcStatus; unsigned ccLeft = sizeof(_awcStatus) / sizeof(WCHAR) - 1;
// Changed srShadow and srAnnealing to just be "Merge" so the end user won't have
// to be told what shadow and annealing merges are. KISS
if ( state.eState & CI_STATE_SHADOW_MERGE ) { wsprintf( _awcStatus, STRINGRESOURCE( srShadow ), state.dwMergeProgress ); ccLeft -= wcslen( _awcStatus ); } else if ( state.eState & CI_STATE_ANNEALING_MERGE ) { wsprintf( _awcStatus, STRINGRESOURCE( srAnnealing ), state.dwMergeProgress ); ccLeft -= wcslen( _awcStatus ); } else if ( state.eState & CI_STATE_MASTER_MERGE ) { wsprintf( _awcStatus, STRINGRESOURCE( srMaster ), state.dwMergeProgress ); ccLeft -= wcslen( _awcStatus ); } else if ( state.eState & CI_STATE_MASTER_MERGE_PAUSED ) { RtlCopyMemory( _awcStatus, STRINGRESOURCE( srMMPaused ), (ccMMPaused + 1) * sizeof(WCHAR) ); ccLeft -= ccMMPaused; }
ccLeft = AppendToStatus( ccLeft, state, CI_STATE_SCANNING, srScanning, ccScanning ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_HIGH_IO, srHighIo, ccHighIo ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_LOW_MEMORY, srLowMemory, ccLowMemory ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_BATTERY_POWER, srBattery, ccBattery ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_USER_ACTIVE, srUserActive, ccUserActive ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_STARTING, srStarting, ccStarting ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_READING_USNS, srReadingUsns, ccReadingUsns ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_RECOVERING, srRecovering, ccRecovering ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_CONTENT_SCAN_REQUIRED, srScanReq, ccScanReq ); ccLeft = AppendToStatus( ccLeft, state, CI_STATE_READ_ONLY, srReadOnly, ccReadOnly );
// If the status is not "Starting", then it should be "Started" so we don't have
// an empty status field
if ( (!(state.eState & CI_STATE_STARTING)) && ccLeft >= ccStarted+2) { if ( _awcStatus[0] == 0 ) { RtlCopyMemory( _awcStatus, STRINGRESOURCE(srStarted), (ccStarted+1) * sizeof(WCHAR) ); ccLeft -= ccStarted; } else { wcscat( _awcStatus, L", " ); wcscat( _awcStatus, STRINGRESOURCE(srStarted) ); ccLeft -= ccStarted + 2; } } }
unsigned CCatalog::AppendToStatus( unsigned ccLeft, CI_STATE & state, DWORD dwFlag, StringResource & srFlag, unsigned ccFlag ) { if ( state.eState & dwFlag && ccLeft >= ccFlag + 2 ) { if ( _awcStatus[0] == 0 ) { RtlCopyMemory( _awcStatus, STRINGRESOURCE(srFlag), (ccFlag+1) * sizeof(WCHAR) ); ccLeft -= ccFlag; } else { wcscat( _awcStatus, L", " ); wcscat( _awcStatus, STRINGRESOURCE(srFlag) ); ccLeft -= ccFlag + 2; } }
return ccLeft; }
void CCatalog::ClearScopes(IResultData * pResultPane) { // Clear out the display list
pResultPane->DeleteAllRsltItems();
// Delete the entries from the property list
_aScope.Clear(); }
void CCatalog::PopulateScopes() { if ( 0 != _aScope.Count() ) return;
TRY { CMachineAdmin MachineAdmin( _parent.GetMachine() );
XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); XPtr<CScopeEnum> xScopeEnum( xCatalogAdmin->QueryScopeEnum() );
for ( ; xScopeEnum->Next(); ) { XPtr<CScopeAdmin> xScopeAdmin( xScopeEnum->QueryScopeAdmin() );
CScope * pScope = new CScope( *this, xScopeAdmin->GetPath(), xScopeAdmin->GetAlias(), xScopeAdmin->IsExclude(), xScopeAdmin->IsVirtual(), xScopeAdmin->IsShadowAlias() );
_aScope.Add( pScope, _aScope.Count() ); } } CATCH( CException, e ) { ciaDebugOut(( DEB_WARN, "Error enumerating scopes for %ws.\n", _pwcsCat )); } END_CATCH }
// Delete registry values for grouped settings. Deletion ensures that those
// registry parameters are inherited from the service.
// Group1 settings are wcsGenerateCharacterization and
// wcsFilterFilesWithUnknownExtensions
// Group2 settings are wcsIsAutoAlias
// Check to see if parameter groups are available
BOOL CCatalog::DoGroup1SettingsExist() { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); DWORD dwVal; BOOL fParamsExist = xCatalogAdmin->GetDWORDParam( wcsGenerateCharacterization, dwVal ) || xCatalogAdmin->GetDWORDParam( wcsFilterFilesWithUnknownExtensions, dwVal ) || xCatalogAdmin->GetDWORDParam( wcsMaxCharacterization, dwVal );
return fParamsExist; }
BOOL CCatalog::DoGroup2SettingsExist() { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); DWORD dwVal; BOOL fParamsExist = xCatalogAdmin->GetDWORDParam( wcsIsAutoAlias, dwVal );
return fParamsExist; }
void CCatalog::FillGroup1Settings() { BOOL fFilterUnknown, fGenerateCharacterization; ULONG ccCharacterization;
// GetGeneration gets registry params from catalog or
// service (if they don't exist at catalog level)
GetGeneration(fFilterUnknown, fGenerateCharacterization, ccCharacterization); SetGeneration(fFilterUnknown, fGenerateCharacterization, ccCharacterization); }
void CCatalog::FillGroup2Settings() { BOOL fTracking; GetTracking(fTracking); SetTracking(fTracking); }
void CCatalog::DeleteGroup1Settings() { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); xCatalogAdmin->DeleteRegistryParamNoThrow( wcsGenerateCharacterization ); xCatalogAdmin->DeleteRegistryParamNoThrow( wcsFilterFilesWithUnknownExtensions ); xCatalogAdmin->DeleteRegistryParamNoThrow( wcsMaxCharacterization ); }
// Group2 settings are wcsIsAutoAlias
void CCatalog::DeleteGroup2Settings() { // Caller will deal with exceptions
CMachineAdmin MachineAdmin( _parent.GetMachine() ); XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _pwcsCat ) ); xCatalogAdmin->DeleteRegistryParamNoThrow( wcsIsAutoAlias ); }
CCatalogs::CCatalogs() : _fFirstScopeExpansion( TRUE ), _fAbort( FALSE ), _pScopePane( 0 ), _uiTimerIndex( 0xFFFFFFFF ), _wIndexingPos( -1 ), _wQueryingPos( -1 ), _pSnapinData( 0 ) { //
// By default, point at local machine.
//
_xwcsMachine[0] = L'.'; _xwcsMachine[1] = 0; }
CCatalogs::~CCatalogs() { _fAbort = TRUE;
if (0xFFFFFFFF != _uiTimerIndex && gaTimerIds[_uiTimerIndex]) { CLock lock(gmtxTimer);
KillTimer(NULL, gaTimerIds[_uiTimerIndex]); gapCats[_uiTimerIndex] = 0; }
if ( 0 != _pScopePane ) _pScopePane->Release(); }
void CCatalogs::SetMachine( WCHAR const * pwcsMachine ) { unsigned cc = wcslen( pwcsMachine ) + 1;
// Remove leading '\' characters. We don't need them, although they
// are commonly included as part of server names
WCHAR const *pwcsStart = pwcsMachine; while ( *pwcsStart == L'\\' ) { cc--; pwcsStart++; }
_xwcsMachine.SetSize( cc );
RtlCopyMemory( _xwcsMachine.Get(), pwcsStart, cc * sizeof(WCHAR) );
ciaDebugOut((DEB_ITRACE, "Input machine name %ws is converted to %ws\n", pwcsMachine, pwcsStart)); }
void CCatalogs::Init( IConsoleNameSpace * pScopePane ) { Win4Assert( 0 == _pScopePane );
_pScopePane = pScopePane; _pScopePane->AddRef();
// timer stuff
CLock lock(gmtxTimer);
gsIndex++; gapCats[gsIndex-1] = this; _uiTimerIndex = gcMaxCats; gaTimerIds[_uiTimerIndex] = SetTimer(NULL, 0, cRefreshDelay, (TIMERPROC)DisplayTimerProc); gcMaxCats++; }
void CCatalogs::InitHeader( CListViewHeader & Header ) { //
// Initialize header
//
for ( unsigned i = 0; i < sizeof(coldefCatalog)/sizeof(coldefCatalog[0]); i++ ) { if ( _fFirstTime ) coldefCatalog[i].srTitle.Init( ghInstance );
Header.Add( i, STRINGRESOURCE( coldefCatalog[i].srTitle ), LVCFMT_LEFT, MMCLV_AUTO ); }
_fFirstTime = FALSE; }
void CCatalogs::DisplayScope( HSCOPEITEM hScopeItem ) { ciaDebugOut(( DEB_ITRACE, "CCatalogs::DisplayScope (hScopeItem = 0x%x)\n", hScopeItem ));
Populate();
Win4Assert( 0 != _pScopePane );
//
// Squirrel away the parent pointer.
//
if ( 0xFFFFFFFF != hScopeItem ) _hRootScopeItem = hScopeItem;
if ( _hRootScopeItem == 0xFFFFFFFF ) return;
for ( unsigned i = 0; i < _aCatalog.Count(); i++ ) { CCatalog * pCat = _aCatalog.Get( i );
if ( pCat->IsZombie() ) { _pScopePane->DeleteItem( pCat->ScopeHandle(), TRUE );
//
// Delete catalog and move highest entry down.
//
pCat = _aCatalog.Acquire( i ); delete pCat;
if ( _aCatalog.Count() > 0 && _aCatalog.Count() != i ) { pCat = _aCatalog.Acquire( _aCatalog.Count() - 1 ); _aCatalog.Add( pCat, i ); i--; }
continue; }
if (pCat->IsInactive()) { RemoveCatalogFromScope(pCat); continue; }
if ( pCat->IsAddedToScope()) continue;
AddCatalogToScope(pCat); } }
void CCatalogs::AddCatalogToScope(CCatalog *pCat) {
SCOPEDATAITEM item;
RtlZeroMemory( &item, sizeof(item) );
item.mask |= SDI_STR | SDI_IMAGE | SDI_OPENIMAGE; item.nImage = item.nOpenImage = ICON_CATALOG; //item.displayname = (WCHAR *)pCat->GetCat( TRUE );
item.displayname = MMC_CALLBACK;
item.mask |= SDI_PARAM; item.lParam = (LPARAM)pCat;
item.relativeID = _hRootScopeItem;
ciaDebugOut(( DEB_ITRACE, "Inserting scope item %ws (lParam = 0x%x)\n", pCat->GetCat( TRUE ), item.lParam ));
_pScopePane->InsertItem( &item );
pCat->SetScopeHandle( item.ID ); }
void CCatalogs::RemoveCatalogFromScope(CCatalog *pCat) { if (pCat->ScopeHandle()) { _pScopePane->DeleteItem( pCat->ScopeHandle(), TRUE ); pCat->SetScopeHandle(0); } }
//+-------------------------------------------------------------------------
//
// Method: CCatalogs::ReInit, public
//
// Synopsis: Re-Initialize catalogs node to default state
//
// History: 27-Jul-1998 KyleP Created
//
// Notes: Used when MMCN_REMOVE_CHILDREN is sent to snapin, and we
// need to blast away all state.
//
//--------------------------------------------------------------------------
SCODE CCatalogs::ReInit() { SCODE sc = S_OK;
Win4Assert( 0 != _pScopePane );
_fAbort = TRUE;
//
// Get rid of the old timer.
//
if ( 0xFFFFFFFF != _uiTimerIndex && gaTimerIds[_uiTimerIndex] ) { CLock lock(gmtxTimer);
KillTimer(NULL, gaTimerIds[_uiTimerIndex]); gapCats[_uiTimerIndex] = 0; }
//
// And the old catalogs...
//
while ( _aCatalog.Count() > 0 ) { RemoveCatalogFromScope( _aCatalog.Get( _aCatalog.Count()-1 ) ); delete _aCatalog.AcquireAndShrink( _aCatalog.Count()-1 ); }
_fAbort = FALSE;
//
// Now, a new timer.
//
CLock lock2(gmtxTimer);
gsIndex++; gapCats[gsIndex-1] = this; _uiTimerIndex = gcMaxCats; gaTimerIds[_uiTimerIndex] = SetTimer(NULL, 0, cRefreshDelay, (TIMERPROC)DisplayTimerProc); gcMaxCats++;
return sc; }
void CCatalogs::Display( BOOL fFirstTime ) { ciaDebugOut(( DEB_ITRACE, "CCatalogs::Display (fFirstTime = %d)\n", fFirstTime ));
for ( unsigned i = 0; i < _aCatalog.Count(); i++ ) { CCatalog * pCat = _aCatalog.Get( i );
if ( pCat->IsZombie() || !pCat->IsAddedToScope() || pCat->IsInactive() ) continue;
if ( pCat->Update() ) { // Ping scope pane...
SCOPEDATAITEM item;
RtlZeroMemory( &item, sizeof(item) );
item.mask |= SDI_STR | SDI_IMAGE | SDI_OPENIMAGE; item.nImage = item.nOpenImage = ICON_CATALOG;
//item.displayname = (WCHAR *)pCat->GetCat( TRUE );
item.displayname = MMC_CALLBACK;
item.mask |= SDI_PARAM; item.lParam = (LPARAM)pCat;
item.ID = pCat->ScopeHandle();
ciaDebugOut(( DEB_ITRACE, "Ping-ing scope item %ws (lParam = 0x%x)\n", pCat->GetCat( TRUE ), item.lParam ));
_pScopePane->SetItem( &item ); } } }
SCODE CCatalogs::AddCatalog( WCHAR const * pwszCatName, WCHAR const * pwszLocation ) { SCODE sc = S_OK;
ciaDebugOut(( DEB_ITRACE, "CCatalogs::AddCatalog( %ws, %ws )\n", pwszCatName, pwszLocation )); //
// First, check to see if the catalog name and location are already used
//
for (ULONG i = 0; i < _aCatalog.Count(); i++) { if (0 == _wcsicmp(_aCatalog[i]->GetCat(TRUE), pwszCatName) || 0 == _wcsicmp(_aCatalog[i]->GetDrive(TRUE), pwszLocation)) { return E_INVALIDARG; } }
TRY { //
// First, add to CI.
//
CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.AddCatalog( pwszCatName, pwszLocation );
//
// Then, to display.
//
XPtr<CCatalog> xCat(new CCatalog( *this, pwszCatName ));
_aCatalog.Add( xCat.GetPointer(), _aCatalog.Count() ); xCat.Acquire(); } CATCH(CException, e) { ciaDebugOut(( DEB_WARN, "AddCatalog( %ws, %ws ) caught exception 0x%x\n", pwszCatName, pwszLocation, sc )); sc = e.GetErrorCode(); } END_CATCH
return sc; }
SCODE CCatalogs::RemoveCatalog( CCatalog * pCat ) { ciaDebugOut(( DEB_ITRACE, "CCatalogs::RemoveCatalog( %ws )\n", pCat->GetCat(TRUE) ));
SCODE sc = S_OK;
TRY { //
// First, remove from CI.
//
CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.RemoveCatalog( pCat->GetCat(TRUE), TRUE ); } CATCH (CException, e) { sc = e.GetErrorCode(); } END_CATCH
//
// Then, from display. Go ahead and Zombify even if catalog wasn't successfully
// removed. Parts of it may have been removed, so it is probably unusable anyway.
//
pCat->Zombify();
return sc; }
void CCatalogs::Quiesce() {
//_Header.Update();
}
void CCatalogs::GetGeneration( BOOL & fFilterUnknown, BOOL & fGenerateCharacterization, ULONG & ccCharacterization ) { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
DWORD dw;
//
// Filter Unknown
//
if ( !MachineAdmin.GetDWORDParam( wcsFilterFilesWithUnknownExtensions, dw ) ) dw = CI_FILTER_FILES_WITH_UNKNOWN_EXTENSIONS_DEFAULT;
fFilterUnknown = (0 != dw);
//
// Characterization. We should check if generatecharacterization flag is set to
// TRUE and also check the characterization size. Only when the flag is set to TRUE
// and size > 0, should we generate characterization.
//
DWORD dwGenCharacterization = 0;
if ( !MachineAdmin.GetDWORDParam( wcsGenerateCharacterization, dwGenCharacterization ) ) dwGenCharacterization = 1;
if ( !MachineAdmin.GetDWORDParam( wcsMaxCharacterization, ccCharacterization ) ) ccCharacterization = CI_MAX_CHARACTERIZATION_DEFAULT;
fGenerateCharacterization = (ccCharacterization > 0) && (0 != dwGenCharacterization); }
void CCatalogs::SetGeneration( BOOL fFilterUnknown, BOOL fGenerateCharacterization, ULONG ccCharacterization ) { //
// fGenerateCharacterization is obsolete.
//
if ( !fGenerateCharacterization ) ccCharacterization = 0;
CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.SetDWORDParam( wcsFilterFilesWithUnknownExtensions, fFilterUnknown ); MachineAdmin.SetDWORDParam( wcsGenerateCharacterization, fGenerateCharacterization ); MachineAdmin.SetDWORDParam( wcsMaxCharacterization, ccCharacterization ); }
void CCatalogs::GetTracking( BOOL & fAutoAlias ) { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
DWORD dw;
if ( !MachineAdmin.GetDWORDParam( wcsIsAutoAlias, dw ) ) dw = CI_IS_AUTO_ALIAS_DEFAULT;
fAutoAlias = (0 != dw); }
void CCatalogs::SetTracking( BOOL fAutoAlias ) { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.SetDWORDParam( wcsIsAutoAlias, fAutoAlias ); }
void CCatalogs::Populate() { if ( 0 != _aCatalog.Count() ) return;
//
// Populate catalog array.
//
CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
XPtr<CCatalogEnum> xCatEnum( MachineAdmin.QueryCatalogEnum() );
while ( 0 != xCatEnum->Next() ) { TRY { XPtr<CCatalog> xCat(new CCatalog( *this, xCatEnum->Name() ));
_aCatalog.Add( xCat.GetPointer(), _aCatalog.Count() ); xCat.Acquire(); } CATCH(CException, e) { ciaDebugOut((DEB_WARN, "Unable to populate admin's display with catalog %ws on machine %ws\n", xCatEnum->Name(), _xwcsMachine.Get() )); } END_CATCH } }
// Differs from Populate in that this only adds newly added catalogs to the
// admin's catalog array.
void CCatalogs::PickupNewCatalogs() { //
// Populate catalog array. Add only newer catalogs
//
CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
XPtr<CCatalogEnum> xCatEnum( MachineAdmin.QueryCatalogEnum() );
while ( 0 != xCatEnum->Next() ) { for (ULONG i = 0; i < _aCatalog.Count(); i++) { if ( 0 == _wcsicmp(xCatEnum->Name(), _aCatalog[i]->GetCat(TRUE)) ) break; }
// Have we found the catalog? If so, continue with the next one.
if (i < _aCatalog.Count()) continue;
// We haven't found the catalog in the list. Add it.
TRY { XPtr<CCatalog> xCat(new CCatalog( *this, xCatEnum->Name() ));
_aCatalog.Add( xCat.GetPointer(), _aCatalog.Count() ); xCat.Acquire(); } CATCH(CException, e) { ciaDebugOut((DEB_WARN, "Unable to populate admin's display with catalog %ws on machine %ws\n", xCatEnum->Name(), _xwcsMachine.Get() )); } END_CATCH } }
void CCatalogs::UpdateActiveState() { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
// Enumerate all the catalogs and add new additions
PickupNewCatalogs();
// Identify what stays and what goes
for (ULONG i = 0; i < _aCatalog.Count(); i++) { TRY { XPtr<CCatalogAdmin> xCatalogAdmin( MachineAdmin.QueryCatalogAdmin( _aCatalog[i]->GetCat(TRUE) ) ); _aCatalog[i]->SetInactive(xCatalogAdmin->IsCatalogInactive()); if (!_aCatalog[i]->IsInactive() && !_aCatalog[i]->IsAddedToScope()) AddCatalogToScope(_aCatalog[i]); } CATCH (CException, e) { // We have an exception attempting to access a catalog, it is either
// deleted or has its registry messed up. Remove it from list of displayed scopes.
RemoveCatalogFromScope(_aCatalog[i]); _aCatalog[i]->Zombify(); } END_CATCH }
// Cleanup...
for ( i = 0; i < _aCatalog.Count(); i++ ) { CCatalog * pCat = _aCatalog.Get( i );
if ( pCat->IsZombie() ) { _pScopePane->DeleteItem( pCat->ScopeHandle(), TRUE );
//
// Delete catalog and move highest entry down.
//
pCat = _aCatalog.Acquire( i ); delete pCat;
if ( _aCatalog.Count() > 0 && _aCatalog.Count() != i ) { pCat = _aCatalog.Acquire( _aCatalog.Count() - 1 ); _aCatalog.Add( pCat, i ); i--; }
continue; }
if ( pCat->IsInactive() ) { if ( pCat->IsAddedToScope() ) RemoveCatalogFromScope(pCat);
continue; }
if ( pCat->IsAddedToScope() ) continue;
AddCatalogToScope(pCat); } }
//
// Implementation of TuneServicePerformance
// wIndexingPos is on a scale of 1 to 3, where 1 is least aggressive
// and 3 is most aggressive. wQueryingPos is on the same scale.
//
SCODE CCatalogs::TuneServicePerformance() { BOOL fServer = IsNTServer(); SCODE sc = S_OK;
// Ensure that these settings were made.
Win4Assert(_wIndexingPos != -1 && _wQueryingPos != -1);
TRY { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.TunePerformance(fServer, _wIndexingPos, _wQueryingPos); } CATCH( CException, e ) { sc = e.GetErrorCode(); ciDebugOut((DEB_WARN, "Caught exception %d (0x%x) attempting to tune performance.", sc, sc)); } END_CATCH
return sc; }
void CCatalogs::SaveServicePerformanceSettings(WORD wIndexingPos, WORD wQueryingPos) { _wIndexingPos = wIndexingPos; _wQueryingPos = wQueryingPos; }
void CCatalogs::GetServicePerformanceSettings(WORD &wIndexingPos, WORD &wQueryingPos) { wIndexingPos = _wIndexingPos; wQueryingPos = _wQueryingPos; }
SCODE CCatalogs::DisableService() { SCODE sc = S_OK;
TRY { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.StopCI();
sc = MachineAdmin.DisableCI() ? S_OK : E_FAIL; } CATCH( CException, e ) { sc = e.GetErrorCode(); ciDebugOut((DEB_WARN, "Caught exception %d (0x%x) attempting to tune performance.", sc, sc)); } END_CATCH
return sc; }
SCODE CCatalogs::EnableService() { SCODE sc = S_OK;
TRY { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
if ( !MachineAdmin.IsCIEnabled() ) sc = MachineAdmin.EnableCI() ? S_OK : E_FAIL; } CATCH( CException, e ) { sc = e.GetErrorCode(); ciDebugOut((DEB_WARN, "Caught exception %d (0x%x) attempting to enable service", sc, sc)); } END_CATCH
return sc; }
SCODE CCatalogs::GetSavedServiceUsage(DWORD &dwUsage, DWORD &dwIdxPos, DWORD &dwQryPos) { SCODE sc = S_OK;
TRY { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
if (!MachineAdmin.GetDWORDParam(wcsServiceUsage, dwUsage)) { // plug in a default value
dwUsage = wUsedOften; }
if (!MachineAdmin.GetDWORDParam(wcsDesiredIndexingPerf, dwIdxPos)) { // plug in a default value
dwIdxPos = wMidPos; }
if (!MachineAdmin.GetDWORDParam(wcsDesiredQueryingPerf, dwQryPos)) { // plug in a default value
dwQryPos = wMidPos; } } CATCH( CException, e ) { sc = e.GetErrorCode(); ciDebugOut((DEB_WARN, "Caught exception %d (0x%x) attempting to retrieve service usage.", sc, sc)); } END_CATCH
return sc; }
SCODE CCatalogs::SaveServiceUsage(DWORD dwUsage, DWORD dwIdxPos, DWORD dwQryPos) { SCODE sc = S_OK;
TRY { CMachineAdmin MachineAdmin( _xwcsMachine.Get() );
MachineAdmin.SetDWORDParam(wcsServiceUsage, dwUsage); MachineAdmin.SetDWORDParam(wcsDesiredIndexingPerf, dwIdxPos); MachineAdmin.SetDWORDParam(wcsDesiredQueryingPerf, dwQryPos); } CATCH( CException, e ) { sc = e.GetErrorCode(); ciDebugOut((DEB_WARN, "Caught exception %d (0x%x) attempting to save service usage.", sc, sc)); } END_CATCH
return sc; }
void CALLBACK DisplayTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) { CLock lock(gmtxTimer);
// seek the index of the catalog associated with this timer event
for (UINT i = 0; i < gcMaxCats; i++) if (gaTimerIds[i] == idEvent) break;
if (i >= gcMaxCats) { Win4Assert(!"How did this happen?"); return; }
// Fix for bug 150471
// If the snapin went away just as the timer triggered a timer proc,
// and the destructor in CCatalogs gets to the lock before this
// function, then gapCats[i] will be 0. That is what happened in
CCatalogs *pCats = gapCats[i];
if (0 == pCats || pCats->_fAbort) return;
// Cause display
pCats->Display( FALSE );
// Special case: Update the status of the iconbar. This is only needed for
// the case where the service was started. Service startup could take a while,
// and we don't know how long it could take. So we cannot wait to update the
// display when the service is actually started. Instead, we will check frequently
// and update the status.
TRY { CMachineAdmin MachineAdmin( pCats->IsLocalMachine() ? 0 : pCats->GetMachine() );
if ( MachineAdmin.IsCIStarted() && 0 != pCats->SnapinData() ) { pCats->SnapinData()->SetButtonState(comidStartCITop, ENABLED, FALSE); pCats->SnapinData()->SetButtonState(comidStopCITop, ENABLED, TRUE); pCats->SnapinData()->SetButtonState(comidPauseCITop, ENABLED, TRUE);
// We only want to update once after the service has started. If the service
// is stopped and restarted, the pointer will be set to an appropriate value
// at a later time, so we can go ahead and get rid of the snapindata ptr for now.
pCats->SetSnapinData( 0 ); } } CATCH(CException, e) { // Nothing specific to do in this case
} END_CATCH }
|