Example #1
0
///////////////////////////////////////////////////////////////////////////////
// CUnitDiskUIHandler
///////////////////////////////////////////////////////////////////////////////
UINT CUnitDiskUIHandler::GetIconID(CDiskObjectPtr obj) const
{
	ATLASSERT(dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL);
	CUnitDiskObjectPtr unitDisk = 
		boost::dynamic_pointer_cast<CUnitDiskObject>(obj);
	CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler();

	if ( !obj->IsUsable() )
		return IDI_ND_BADKEY;

	if ( handler->IsHDD() )
	{
		if ( handler->IsBound() )
		{
			if ( handler->IsMaster() )
			{
				return IDI_ND_INUSE;
			}
			else
			{
				return IDI_ND_SLAVE;
			}
		}
		else
		{
			return IDI_ND_INUSE;
		}
	}
	else
	{
		// TODO : We need a new icon for this type(DVD, FLASH, MO.. ETC)
		return IDI_ND_INUSE;	
	}
}
Example #2
0
void CMirrorWorkThread::RebindMirror()
{
	// Get list of disks involved in the previous mirroring.
	// NOTE : Because disks aggregated can also be mirrored,
	//	there can be more than two disks involved in the mirroring.
	CDiskObjectPtr aggregationRoot;
	aggregationRoot = m_pSource->GetParent();
	while ( !aggregationRoot->GetParent()->IsRoot() )
	{
		aggregationRoot = aggregationRoot->GetParent();
	}

	// Mark all the bitmaps dirty.
	m_pSource->OpenExclusive();
	m_pDest->OpenExclusive();
	m_pSource->MarkAllBitmap();

	CUnitDiskInfoHandlerPtr pHandler = m_pSource->GetInfoHandler();
	aggregationRoot->Rebind( 
						m_pDest, 
						pHandler->GetPosInBind() ^ 0x01
						);
	aggregationRoot->CommitDiskInfo(TRUE);


	// Write binding information to the destination disk
	m_pDest->Mirror(m_pSource);
	m_pDest->CommitDiskInfo(TRUE);
	m_bRebound = TRUE;

	m_pSource->Close();
	m_pDest->Close();
}
Example #3
0
void CMainFrame::OnCommand(UINT /*wNotifyCode*/, int wID, HWND /*hwndCtl*/)
{
	ENTER_CRITICAL_SECTION(&m_csThreadRefreshStatus);

	// Commands which do not change the tree are sent to the object directly.
	CTreeItem itemSelected = m_view.GetSelectedItem();

	if ( itemSelected.IsNull() )
	{
		LEAVE_CRITICAL_SECTION(&m_csThreadRefreshStatus);
		return;
	}

	CDiskObjectPtr obj;
	const CObjectUIHandler *phandler;
	obj = m_mapObject[m_view.GetItemData(itemSelected)];
	ATLASSERT( obj.get() != NULL );
	phandler = CObjectUIHandler::GetUIHandler( obj );
	phandler->OnCommand( obj, wID );
	
	m_view.UpdateDiskObject( obj );

	OnSelChanged(NULL);

	LEAVE_CRITICAL_SECTION(&m_csThreadRefreshStatus);
}
Example #4
0
///////////////////////////////////////////////////////////////////////////////
// CDiskObjectComposite
///////////////////////////////////////////////////////////////////////////////
void CDiskObjectComposite::AddChild(CDiskObjectPtr _this, CDiskObjectPtr child)
{
	ATLASSERT( this == _this.get() );
	child->SetParent(_this);
	CDiskObjectList::push_back(child);

}
Example #5
0
void CNBTreeView::Visit(CDiskObjectPtr o)
{
	const CObjectUIHandler *pHandler = CObjectUIHandler::GetUIHandler(o);

	switch ( m_nAction )
	{
	case NDASBINDVIEW_INSERT_OBJECT:
		{
			m_htiLast = CTreeViewCtrlEx::InsertItem( 
				pHandler->GetTitle(o), 
				pHandler->GetIconIndex(o),
				pHandler->GetSelectedIconIndex(o),
				m_htiParent,
				TVI_LAST 
				);
			m_htiLast.SetData( o->GetUniqueID() );
			m_mapIDToTreeItem[o->GetUniqueID()] = m_htiLast;
			Expand(m_htiParent, TVE_EXPAND);
		}
		break;
	case NDASBINDVIEW_UPDATE_OBJECT:
		{
			CTreeItem htiUpdate = m_mapIDToTreeItem[o->GetUniqueID()];
			htiUpdate.SetText( pHandler->GetTitle(o) );
			htiUpdate.SetImage(
				pHandler->GetIconIndex(o),
				pHandler->GetSelectedIconIndex(o)
				);
		}
	}
};
Example #6
0
LRESULT CNBBindListViewCtrl::OnGetDispInfo(LPNMHDR lParam)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(lParam);
	CDiskObjectPtr obj;
	const CObjectUIHandler *phandler;

	obj = m_mapObject[static_cast<UINT>(pDispInfo->item.lParam)];
	ATLASSERT( obj.get() != NULL );

	phandler = CObjectUIHandler::GetUIHandler( obj );
	
	switch ( pDispInfo->item.iSubItem )
	{
	case 0: // Index
		::_stprintf(
			pDispInfo->item.pszText,
			_T("%d"), 
			pDispInfo->item.iItem
			);
		break;
	case 1:	// Name
		::_tcsncpy( 
			pDispInfo->item.pszText,  
			obj->GetTitle(),
			pDispInfo->item.cchTextMax-1
			);
		break;
	case 2:	// ID
/*
		::_tcsncpy(
			pDispInfo->item.pszText,  
			phandler->GetStringID( obj ),
			pDispInfo->item.cchTextMax-1
			);
		break;
	case 3: // Size
*/
		{
			WTL::CString strSize;
			strSize.FormatMessage(
				IDS_LISTVIEW_SIZE_IN_GB,
				phandler->GetSizeInMB( obj ) / 1024,
				(phandler->GetSizeInMB( obj ) % 1024) / 10
				);
			::_tcsncpy(
				pDispInfo->item.pszText,  
				strSize,
				pDispInfo->item.cchTextMax-1
				);
		}		
	default:
		break;
	}
	pDispInfo->item.pszText[pDispInfo->item.cchTextMax-1] = '\0';
	return 0;
}
Example #7
0
///////////////////////////////////////////////////////////////////////////////
// CUnsupportedDiskUIHandler
///////////////////////////////////////////////////////////////////////////////
CCommandSet CUnsupportedDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	ATLASSERT( dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL);
	CCommandSet setCommand;

	setCommand.push_back ( CCommand( IDM_TOOL_CLEARDIB, 
							(obj->GetAccessMask() & GENERIC_WRITE)
							) 
						 );
	return setCommand;							
}
Example #8
0
BOOL CUnsupportedDiskUIHandler::OnClearDIB(CDiskObjectPtr obj) const
{
	ATLASSERT( dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL);

	WTL::CString strWarning;
	strWarning.FormatMessage( 
			IDS_UIHANDLER_CLEARDIB_CONFIRM,
			obj->GetTitle()
			);
	WTL::CString strTitle;
	strTitle.LoadString(IDS_APPLICATION);
	if ( MessageBox(::GetFocus(), strWarning, strTitle, MB_YESNO | MB_ICONWARNING) != IDYES )
	{
		return TRUE;
	}
	CUnitDiskObjectPtr unitDisk = 
		boost::dynamic_pointer_cast<CUnitDiskObject>(obj);
	if ( !unitDisk->CanAccessExclusive() )
	{
		WTL::CString strMsg;
		strMsg.LoadString( IDS_FAIL_TO_ACCESS_EXCLUSIVELY );
		MessageBox( 
			::GetFocus(),
			strMsg,
			strTitle,
			MB_OK | MB_ICONWARNING
			);
		return TRUE;
	}
	try {
		unitDisk->Open( TRUE );
        unitDisk->Initialize( unitDisk );
		unitDisk->CommitDiskInfo();
		unitDisk->Close();
	}
	catch( CNDASException & )
	{
		unitDisk->Close();
		WTL::CString strMsg;
		strMsg.LoadString ( IDS_UIHANDLER_CLEARDIB_FAIL );
		MessageBox( 
			::GetFocus(),
			strMsg,
			strTitle,
			MB_OK | MB_ICONERROR
			);
		return TRUE;
	}
	WTL::CString strMsg;
	strMsg.LoadString( IDS_UIHANDLER_CLEARDIB_SUCCESS );
	return TRUE;
}
Example #9
0
void CNBListViewCtrl::DeleteDiskObject(CDiskObjectPtr o)
{
	int nItemCount = CListViewCtrl::GetItemCount();
	for (int i=0; i < nItemCount; i++ )
	{
		if ( GetItemData(i) == o->GetUniqueID() )
		{
			CListViewCtrl::DeleteItem( i );
			break;
		}
	}
	m_mapObject.erase( o->GetUniqueID() );
}
Example #10
0
void CUnitDiskObject::Initialize(CDiskObjectPtr _this)
{
	ATLASSERT( this == _this.get() );
	m_pHandler->Initialize(
		boost::dynamic_pointer_cast<CUnitDiskObject>(_this)
		);
}
Example #11
0
CDiskObjectList CLanUnitDiskObject::UnBind(CDiskObjectPtr _this)
{
	ATLASSERT( this == _this.get() );
	CDiskObjectList listUnbound;

	// If the disk is aggregated, the MBR block of the disk should be cleaned
	// to prevent unexpected behavior of disks after unbinding.
	CDataSector dataSector( SECTOR_MBR_COUNT );
	dataSector.SetLocation( 0 );
	if ( m_pHandler->IsBoundAndNotSingleMirrored() )
	{
		try{
			dataSector.WriteAccept( &m_session );
		}
		catch( CNDASException &e )
		{
			NDAS_THROW_EXCEPTION_CHAIN_STR(
				CDiskException,
				CDiskException::ERROR_FAIL_TO_INITIALIZE,
				_T("Fail to clean MBR"),
				e);
		}
	}

	// Clear bind information
	m_pHandler->UnBind(
		boost::dynamic_pointer_cast<CUnitDiskObject>(_this)
		);

	listUnbound.push_back(_this);
	return listUnbound;
}
Example #12
0
UINT CObjectUIHandler::GetSizeInMB(CDiskObjectPtr obj) const
{
	_int64 nSize;
	nSize = obj->GetUserSectorCount() / ( 1024 / NDAS_BLOCK_SIZE )  / 1024;
	                                   /* KB per sector */		/* MB per KB */
	return static_cast<UINT>(nSize);
}
Example #13
0
int CNBListViewCtrl::FindDiskObjectItem(CDiskObjectPtr o)
{
	LVFINDINFO info;

	info.flags = LVFI_PARAM;
	info.lParam = o->GetUniqueID();
	return CListViewCtrl::FindItem(&info, -1);
}
Example #14
0
void CNBTreeView::InsertDiskObject(CDiskObjectPtr o, CDiskObjectPtr parent)
{
	if ( parent.get() == NULL )
	{
		m_htiParent = TVI_ROOT;
		m_htiLast = m_htiParent;
	}
	else 
	{
		m_htiParent = m_mapIDToTreeItem[parent->GetUniqueID()];
		if ( m_htiParent.IsNull() )
			m_htiParent = TVI_ROOT;
		m_htiLast = m_htiParent;
	}

	m_nAction = NDASBINDVIEW_INSERT_OBJECT;
	o->Accept( o, this );
}
Example #15
0
CCommandSet CEmptyDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	ATLASSERT( dynamic_cast<CEmptyDiskObject*>(obj.get()) != NULL);
	CCommandSet setCommand;
	CEmptyDiskObjectPtr unitDisk =
		boost::dynamic_pointer_cast<CEmptyDiskObject>(obj);

	return setCommand;
}
Example #16
0
BOOL CRAID4DiskUIHandler::OnRecover(CDiskObjectPtr obj) const
{
	ATLASSERT( dynamic_cast<CRAID4DiskObject*>(obj.get()) != NULL );
	
	CRAID4DiskObjectPtr raid4Disk = 
		boost::dynamic_pointer_cast<CRAID4DiskObject>(obj);

	if(!raid4Disk->IsDirty())
	{
		WTL::CString strMsg;
		strMsg.LoadString(IDS_WARNING_NOT_NEED_RECOVER );
		WTL::CString strTitle;
		strTitle.LoadString(IDS_APPLICATION);
		MessageBox( 
			::GetFocus(),
			strMsg,
			strTitle,
			MB_OK | MB_ICONERROR
			);
		return TRUE;
	}

	std::list<CDiskObjectPtr>::iterator it;
	CUnitDiskObjectPtr pUnitDisk;

	it = raid4Disk->begin();
	INT32 iDirty;
	for(iDirty = raid4Disk->GetDirtyDisk(); iDirty > 0; iDirty--)
		it++;

	pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);

	CRecoverDlg dlgRecover(FALSE, IDS_LOGDEV_TYPE_DISK_RAID4, IDS_RECOVERDLG_TASK_RECOVER);

	dlgRecover.SetMemberDevice(pUnitDisk);
	dlgRecover.DoModal();

	CNdasHIXChangeNotify HixChangeNotify(pGetNdasHostGuid());
	BOOL bResults = HixChangeNotify.Initialize();
	if(bResults)
	{
		NDAS_UNITDEVICE_ID unitDeviceId;

		for(it = raid4Disk->begin(); it != raid4Disk->end(); ++it)
		{
			pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);
			CopyMemory(unitDeviceId.DeviceId.Node,
				pUnitDisk->GetLocation()->GetUnitDiskLocation()->MACAddr,
				sizeof(unitDeviceId.DeviceId.Node));
			unitDeviceId.UnitNo = 
				pUnitDisk->GetLocation()->GetUnitDiskLocation()->UnitNumber;
			HixChangeNotify.Notify(unitDeviceId);
		}
	}

	return TRUE;
}
Example #17
0
CCommandSet CAggrDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	CCommandSet setCommand;

	setCommand.push_back( 
		CCommand(IDM_TOOL_UNBIND, obj->GetAccessMask() & GENERIC_WRITE)
		);
	return setCommand;
}
Example #18
0
BOOL CUnitDiskUIHandler::OnCommand(CDiskObjectPtr obj, UINT nCommandID) const
{
	ATLASSERT( dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL);

	switch( nCommandID )
	{
	case IDM_TOOL_SYNCHRONIZE:
		{
			// Delegate command to parent
			const CObjectUIHandler *phandler = 
				CObjectUIHandler::GetUIHandler( obj->GetParent() );
			return phandler->OnCommand( obj->GetParent(), nCommandID );
		}
	case IDM_TOOL_PROPERTY:
		return OnProperty( obj );
	}

	return FALSE;
}
Example #19
0
CCommandSet CRAID0DiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	CCommandSet setCommand;

	// AING_TO_DO : add IDM_RAID0_UNBIND
	setCommand.push_back( 
		CCommand(IDM_TOOL_UNBIND, obj->GetAccessMask() & GENERIC_WRITE)
		);
	return setCommand;
}
Example #20
0
BOOL CAggrDiskUIHandler::OnCommand(CDiskObjectPtr obj, UINT nCommandID) const
{
	ATLASSERT( dynamic_cast<CAggrDiskObject*>(obj.get()) != NULL );
	switch( nCommandID )
	{
	case IDM_TOOL_PROPERTY:
		return OnProperty( obj );
	}
	return FALSE;
}
Example #21
0
///////////////////////////////////////////////////////////////////////////////
// CRootDiskObject
///////////////////////////////////////////////////////////////////////////////
void CRootDiskObject::Accept(CDiskObjectPtr _this, CDiskObjectVisitor *v)
{
	ATLASSERT( this == _this.get() );
	//v->IncDepth();
	iterator itr;
	for ( itr = begin(); itr != end(); itr++ )
	{
		(*itr)->Accept(*itr, v);
	}
	//v->DecDepth();
}
Example #22
0
void CNBListViewCtrl::AddDiskObject(CDiskObjectPtr o)
{
	LVITEM lvItem = { 0 };
	const CObjectUIHandler *pHandler = CObjectUIHandler::GetUIHandler(o);
	WTL::CString strName = pHandler->GetTitle(o);
	WTL::CString strCapacity;

	strCapacity.FormatMessage( 
		IDS_DISKPROPERTYPAGE_SIZE_IN_GB,
		pHandler->GetSizeInMB( o ) / 1024,
		(pHandler->GetSizeInMB( o ) % 1024) / 10 
		);

	lvItem.mask		= LVIF_TEXT | LVIF_PARAM;
	lvItem.iItem	= GetItemCount();
	lvItem.pszText	= strName.LockBuffer(); //LPSTR_TEXTCALLBACK;
	lvItem.lParam	= static_cast<LPARAM>(o->GetUniqueID());
	CListViewCtrl::InsertItem( &lvItem );
	CListViewCtrl::SetItemText(lvItem.iItem, 1, strCapacity.LockBuffer() );
	m_mapObject[o->GetUniqueID()] = o;
}
Example #23
0
int CNBListViewCtrl::CompareItems(CDiskObjectPtr obj1, CDiskObjectPtr obj2)
{
	int signAsc = m_abSortAsc[m_iColSort]? 1 : -1;

	switch(m_iColSort)
	{
	case 0:
		return signAsc * obj1->GetTitle().Compare( obj2->GetTitle() );
		break;
	case 1:
		return signAsc * obj1->GetStringDeviceID().Compare( obj2->GetStringDeviceID() );
		break;
	case 2:
		{
			_int64 size1, size2;
			size1 = obj1->GetUserSectorCount();
			size2 = obj2->GetUserSectorCount();
			if ( size1 > size2 )
				return signAsc;
			else if ( size1 == size2 )
				return 0;
			else
				return (-1) * signAsc;
		}
		break;
	default:
		break;
	}
	return 0;
}
Example #24
0
WTL::CString CObjectUIHandler::GetType(CDiskObjectPtr obj) const
{
	WTL::CString strTitle;

	if(obj->IsUnitDisk())
	{
		if(dynamic_cast<CEmptyDiskObject*>(obj.get()) != NULL)
		{
			strTitle.LoadString(IDS_UNIDEV_TYPE_DISK_EMPTY);
		}
		else
		{
			strTitle.LoadString(IDS_LOGDEV_TYPE_SINGLE_DISK);
		}
	}
	else
	{
		CDiskObjectCompositePtr pDiskObjectComposite = 
			boost::dynamic_pointer_cast<CDiskObjectComposite>(obj);


		switch(pDiskObjectComposite->GetNDASMediaType())
		{
		case NMT_SINGLE: strTitle.LoadString(IDS_LOGDEV_TYPE_SINGLE_DISK); break;
		case NMT_AGGREGATE: strTitle.LoadString(IDS_LOGDEV_TYPE_AGGREGATED_DISK); break;
		case NMT_MIRROR: strTitle.LoadString(IDS_LOGDEV_TYPE_MIRRORED_DISK); break;
		case NMT_RAID0: strTitle.LoadString(IDS_LOGDEV_TYPE_DISK_RAID0); break;
		case NMT_RAID1: strTitle.LoadString(IDS_LOGDEV_TYPE_DISK_RAID1); break;
		case NMT_RAID4: strTitle.LoadString(IDS_LOGDEV_TYPE_DISK_RAID4); break;
		case NMT_CDROM: strTitle.LoadString(IDS_LOGDEV_TYPE_DVD_DRIVE); break;
		case NMT_OPMEM: strTitle.LoadString(IDS_LOGDEV_TYPE_MO_DRIVE); break;
		case NMT_FLASH: strTitle.LoadString(IDS_LOGDEV_TYPE_CF_DRIVE); break;
		default:
			strTitle.FormatMessage(IDS_LOGDEV_TYPE_UNKNOWN_FMT, 
				pDiskObjectComposite->GetNDASMediaType());
		}
	}

	return strTitle;
}
Example #25
0
WTL::CString CObjectUIHandler::GetTitle(CDiskObjectPtr obj) const
{
	WTL::CString strTitle;

	if(obj->IsUnitDisk())
	{
		if(dynamic_cast<CEmptyDiskObject*>(obj.get()) != NULL)
		{
			strTitle.LoadString(IDS_UNIDEV_TYPE_DISK_EMPTY);
		}
		else
		{
			strTitle = obj->GetTitle();
		}
	}
	else
	{
		strTitle = GetType(obj);
	}

	return strTitle;
}
Example #26
0
void CMainFrame::RefreshAction()
{
	int iItemSelected;

//	UIEnable(IDM_AGGR_BIND, FALSE);
	UIEnable(IDM_AGGR_UNBIND, FALSE);
	UIEnable(IDM_AGGR_SYNCHRONIZE, FALSE);
	UIEnable(IDM_AGGR_ADDMIRROR, FALSE);

	if (-1 != (iItemSelected = m_viewTreeList.GetSelectedItemData()))
	{
		CDiskObjectPtr obj = m_mapObject[iItemSelected];
		ATLASSERT( obj.get() != NULL );
		CCommandSet cmdSet = 
			CObjectUIHandler::GetUIHandler(obj)->GetCommandSet(obj);
		CCommandSet::iterator itr;
		for ( itr = cmdSet.begin(); itr != cmdSet.end(); itr++ )
		{
			UIEnable( itr->GetID(), !itr->IsDisabled() );
		}
	}
}
Example #27
0
LRESULT CMainFrame::OnSelChanged(LPNMHDR /*lpNLHDR*/)
{
	CTreeItem itemSelected;
	itemSelected = m_view.GetSelectedItem();

	UIEnable(IDM_AGGR_UNBIND, FALSE);
	UIEnable(IDM_AGGR_SYNCHRONIZE, FALSE);
	UIEnable(IDM_AGGR_ADDMIRROR, FALSE);
	if ( !itemSelected.IsNull() )
	{
		CDiskObjectPtr obj = m_mapObject[itemSelected.GetData()];
		ATLASSERT( obj.get() != NULL );
		CCommandSet cmdSet = 
			CObjectUIHandler::GetUIHandler(obj)->GetCommandSet(obj);
		CCommandSet::iterator itr;
		for ( itr = cmdSet.begin(); itr != cmdSet.end(); itr++ )
		{
			UIEnable( itr->GetID(), !itr->IsDisabled() );
		}
	}
	return 0;
}
Example #28
0
PropertyList CRAID4DiskUIHandler::GetPropertyList(CDiskObjectPtr obj) const
{
	PropertyList propList;
	PropertyListItem propItem;
	WTL::CString strBuffer;

	//propItem[0] = _T("Binding type");
	propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_NUM_BOUND_DISK );
	strBuffer.Format( _T("%d"), obj->GetDiskCountInBind() );
	propItem.strValue = strBuffer;
	propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_NUM_BOUND_DISK_TOOLTIP );
	propList.push_back( propItem );
	return propList;	
}
Example #29
0
CCommandSet CRAID4DiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	CCommandSet setCommand;
	BOOL bCanWrite;

	CRAID4DiskObjectPtr disk = 
		boost::dynamic_pointer_cast<CRAID4DiskObject>(obj);

	setCommand.push_back( 
		CCommand(IDM_TOOL_UNBIND, obj->GetAccessMask() & GENERIC_WRITE)
		);
	setCommand.push_back(
		CCommand(IDM_TOOL_SYNCHRONIZE, disk->IsDirty() && disk->HasWriteAccess()));

	setCommand.push_back(
		CCommand(IDM_TOOL_REPAIR, 1 == disk->GetMissingMemberCount()));

	setCommand.push_back(
		CCommand(IDM_TOOL_SPAREADD, obj->GetAccessMask() & GENERIC_WRITE)
		);

	return setCommand;
}
Example #30
0
BOOL CMirDiskUIHandler::OnCommand(CDiskObjectPtr obj, UINT nCommandID) const
{
	ATLASSERT( dynamic_cast<CMirDiskObject*>(obj.get()) != NULL );
	switch ( nCommandID )
	{
	case IDM_TOOL_SYNCHRONIZE:
		return OnSynchronize( obj );
	case IDM_TOOL_PROPERTY:
		return OnProperty( obj );
	case IDM_TOOL_MIGRATE:
		return OnMigrate( obj );
	}
	return FALSE;
}