コード例 #1
0
ファイル: ndasobject.cpp プロジェクト: yzx65/ndas4windows
UINT32
CMirDiskObject::GetNDASMediaType() const
{
	if(::IsEmptyDisk(FirstDisk()))
	{
		if(::IsEmptyDisk(SecondDisk()))
			return NMT_INVALID;
		else
		{
			CUnitDiskObjectPtr unitDisk = 
				boost::dynamic_pointer_cast<CUnitDiskObject>(SecondDisk());
			CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler();

			return unitHandler->GetNDASMediaType();
		}
	}
	else
	{
		CUnitDiskObjectPtr unitDisk = 
			boost::dynamic_pointer_cast<CUnitDiskObject>(FirstDisk());
		CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler();

		return unitHandler->GetNDASMediaType();
	}
}
コード例 #2
0
BOOL 
HasSameBoundDiskList(CUnitDiskObjectPtr first, CUnitDiskObjectPtr second)
{
	CDiskLocationVector vtFirst, vtSecond;
	CUnitDiskInfoHandlerPtr handlerFirst, handlerSecond;

	handlerFirst = first->GetInfoHandler();
	handlerSecond = second->GetInfoHandler();

	if ( !handlerFirst->IsBound() || !handlerSecond->IsBound() )
	{
		return FALSE;
	}

	vtFirst = handlerFirst->GetBoundDiskLocations( first->GetLocation() );
	vtSecond = handlerSecond->GetBoundDiskLocations( second->GetLocation() );

	if ( vtFirst.size() != vtSecond.size() )
		return FALSE;

	for ( UINT i=0; i < vtFirst.size(); i++ )
	{
		if ( !vtFirst[i]->Equal(vtSecond[i]) )
			return FALSE;
	}
	return TRUE;
}
コード例 #3
0
ファイル: nbuihandler.cpp プロジェクト: yzx65/ndas4windows
///////////////////////////////////////////////////////////////////////////////
// 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;	
	}
}
コード例 #4
0
ファイル: nbuihandler.cpp プロジェクト: yzx65/ndas4windows
const CObjectUIHandler *CObjectUIHandler::GetUIHandler(CDiskObjectPtr obj)
{
	// TODO : More sophisticated way of determining uihandler based on the
	//		  status of the disks is necessary.
	static CAggrDiskUIHandler aggrUIHandler;
	static CMirDiskUIHandler mirUIHandler;
	static CEmptyDiskUIHandler emptyUIHandler;
	static CRAID4DiskUIHandler raid4UIHandler;
	static CUnitDiskUIHandler unitDiskUIHandler;
	static CUnsupportedDiskUIHandler unsupportedDiskUIHandler;

	if ( dynamic_cast<const CAggrDiskObject*>(obj.get()) != NULL )
		return &aggrUIHandler;
	if ( dynamic_cast<const CMirDiskObject*>(obj.get()) != NULL )
		return &mirUIHandler;
	if ( dynamic_cast<const CRAID4DiskObject*>(obj.get()) != NULL )
		return &raid4UIHandler;
	if ( dynamic_cast<const CEmptyDiskObject*>(obj.get()) != NULL )
		return &emptyUIHandler;
	if ( dynamic_cast<const CUnitDiskObject*>(obj.get()) != NULL )
	{
		CUnitDiskObjectPtr unitDisk =
			boost::dynamic_pointer_cast<CUnitDiskObject>(obj);
		CUnitDiskInfoHandlerPtr infoHandler = unitDisk->GetInfoHandler();
		if ( infoHandler->HasValidInfo() )
			return &unitDiskUIHandler;
		else
			return &unsupportedDiskUIHandler;
	}
	return &unitDiskUIHandler;		
}
コード例 #5
0
ファイル: nbuihandler.cpp プロジェクト: yzx65/ndas4windows
PropertyList CUnitDiskUIHandler::GetPropertyList(CDiskObjectPtr obj) const
{
	PropertyList propList;
	PropertyListItem propItem;
	WTL::CString strBuffer;
	CUnitDiskObjectPtr unitDisk = 
		boost::dynamic_pointer_cast<CUnitDiskObject>(obj);
	CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler();
	CHDDDiskInfoHandler *pHDDHandler = 
		dynamic_cast<CHDDDiskInfoHandler*>(handler.get());
	if ( pHDDHandler != NULL )
	{
		// TODO : String resources
		propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_MODEL );
		propItem.strValue = pHDDHandler->GetModelName();
		propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_MODEL_TOOLTIP );
		propList.push_back( propItem );

		propItem.strName.LoadString( IDS_UIHANDLER_PROPERTY_SERIALNO );
		propItem.strValue = pHDDHandler->GetSerialNo();
		propItem.strToolTip.LoadString( IDS_UIHANDLER_PROPERTY_SERIALNO_TOOLTIP );
		propList.push_back( propItem );
	}
	return propList;
}
コード例 #6
0
CUnitDiskObjectPtr 
FindMirrorDisk(CUnitDiskObjectPtr src, CUnitDiskObjectList disks)
{
	CUnitDiskInfoHandlerPtr handler = src->GetInfoHandler();
	ATLASSERT( handler->IsMirrored() );
	CUnitDiskObjectList::const_iterator found;

	found = std::find_if ( disks.begin(), disks.end(),
		std::bind1st( CDiskLocationEqual(), handler->GetPeerLocation() )
		);
	if ( found == disks.end() )
	{
		return CUnitDiskObjectPtr();
	}
	return *found;
}
コード例 #7
0
void CUnBindDlg::SetDiskToUnbind(CDiskObjectPtr obj)
{
	 m_pDiskUnbind = obj; 

	CFindIfVisitor<TRUE> unitDiskFinder;
	CDiskObjectList listUnbind;	// List of disks to unbind
	listUnbind = unitDiskFinder.FindIf( m_pDiskUnbind, IsUnitDisk);
	
	//
	// Data is deleted only when the disks are aggregated
	// Thus, change message if they are not.
	//
	CUnitDiskObjectPtr unitDisk = 
		boost::dynamic_pointer_cast<CUnitDiskObject>(listUnbind.front());
	if ( unitDisk->GetInfoHandler()->IsBoundAndNotSingleMirrored() )
	{
		IDD = IDD_UNBIND_MIRROR;
	}
}
コード例 #8
0
UINT32
CRAID4DiskObject::GetNDASMediaType() const
{
	CUnitDiskObjectPtr pUnitDisk;
	std::list<CDiskObjectPtr>::iterator it;

	for(it = begin(); it != end(); ++it)
	{
		pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);
		if(!::IsEmptyDisk(pUnitDisk))
		{
			CUnitDiskInfoHandlerPtr unitHandler = pUnitDisk->GetInfoHandler();

			return unitHandler->GetNDASMediaType();
		}
	}	

	return NMT_INVALID;
}
コード例 #9
0
ファイル: ndasobject.cpp プロジェクト: yzx65/ndas4windows
UINT32 CDiskObjectComposite::GetNDASMediaType() const
{
	UINT32 iMediaType = NMT_INVALID;

	// return the first NDAS Media type of unit disk which is not NMT_INVALID
	const_iterator itr;
	for ( itr = begin(); itr != end(); ++itr )
	{
		if(::IsEmptyDisk(*itr))
			continue;

		if(!(*itr)->IsUnitDisk())
		{
			CMirDiskObjectPtr mirDisk = 
				boost::dynamic_pointer_cast<CMirDiskObject>(*itr);

			if(mirDisk)
			{
				iMediaType = mirDisk->GetNDASMediaType();
				if(NMT_INVALID != iMediaType)
					return iMediaType;
			}
			else
			{
				return NMT_INVALID;
			}
		}

		if(0 == (*itr)->GetDiskCount()) // skip empty one
			continue;

		CUnitDiskObjectPtr unitDisk = 
			boost::dynamic_pointer_cast<CUnitDiskObject>(*itr);
		CUnitDiskInfoHandlerPtr unitHandler = unitDisk->GetInfoHandler();
		
		iMediaType = unitHandler->GetNDASMediaType();
		if(NMT_INVALID != iMediaType)
			return iMediaType;
	}
	return iMediaType;
}
コード例 #10
0
ファイル: nbuihandler.cpp プロジェクト: yzx65/ndas4windows
CCommandSet CUnitDiskUIHandler::GetCommandSet(CDiskObjectPtr obj) const
{
	ATLASSERT( dynamic_cast<CUnitDiskObject*>(obj.get()) != NULL);
	CCommandSet setCommand;
	CUnitDiskObjectPtr unitDisk =
		boost::dynamic_pointer_cast<CUnitDiskObject>(obj);
	CUnitDiskInfoHandlerPtr handler = unitDisk->GetInfoHandler();
	BOOL bCanWrite;

	if ( handler->IsBound() )
	{
		CDiskObjectPtr aggrRoot = unitDisk->GetParent();
		if ( aggrRoot->IsRoot() )
		{
			// This can occur when the tree is updated just after
			// the disk is bound.
			// This additional if code prevents error.
			setCommand.push_back( CCommand(IDM_TOOL_UNBIND) ); 
		}
		else
		{
			while ( !aggrRoot->GetParent()->IsRoot() )
				aggrRoot = aggrRoot->GetParent();
			// To Unbind, we should have write privilege to all the disks in bind
			setCommand.push_back( CCommand(IDM_TOOL_UNBIND, 
				aggrRoot->GetAccessMask() & GENERIC_WRITE) );
		}
	}
	else
	{
		bCanWrite =  unitDisk->GetAccessMask() & GENERIC_WRITE;
		setCommand.push_back( CCommand(IDM_TOOL_ADDMIRROR, bCanWrite) );
	}

	if ( handler->IsMirrored() )
	{
		CMirDiskObjectPtr parent = 
			boost::dynamic_pointer_cast<CMirDiskObject>(unitDisk->GetParent());
		if ( parent.get() != NULL )
		{
			// To synchronize, we have write privilege to the two disks in mirroring
			setCommand.push_back( CCommand(IDM_TOOL_SYNCHRONIZE, 
									(parent->GetAccessMask() & GENERIC_WRITE) &&
									parent->IsDirty() && !parent->IsBroken() &&
									parent->HasWriteAccess()
									) 
								);
		}
		CDiskObjectPtr aggrRoot = unitDisk->GetParent();
		if ( aggrRoot->IsRoot() )
		{
			// This can occur when the tree is updated just after
			// the disk is bound.
			// This additional if code prevents error.
			setCommand.push_back( CCommand(IDM_TOOL_UNBIND) ); 
		}
		else
		{
			while ( !aggrRoot->GetParent()->IsRoot() )
				aggrRoot = aggrRoot->GetParent();
		}
	}
	else if(NMT_RAID4 == handler->GetNDASMediaType())
	{
		CRAID4DiskObjectPtr parent = 
			boost::dynamic_pointer_cast<CRAID4DiskObject>(unitDisk->GetParent());

		if ( parent.get() != NULL )
		{
			// To synchronize, we have write privilege to the two disks in mirroring
			setCommand.push_back( CCommand(IDM_TOOL_SYNCHRONIZE, 
				(parent->GetAccessMask() & GENERIC_WRITE)
				&& parent->IsDirty() && !parent->IsBroken() 
				) 
				);
		}
	}

	if(unitDisk->IsUnitDisk())
	{
		setCommand.push_back( CCommand(IDM_TOOL_SINGLE) );
	}
	return setCommand;
}
コード例 #11
0
ファイル: ndasbind.cpp プロジェクト: yzx65/ndas4windows
BOOL
WINAPI
NdasBindUnitDevices(PNDAS_UNITDEVICE_GROUP pUnitDeviceIdGroup, NDAS_UNITDEVICE_DISK_TYPE diskType)
{
	int nBindType;
	BOOL bResult;

	_ASSERT(FALSE);
	//
	// Basic validation of parameters
	//
	switch( diskType )
	{
	case NDAS_UNITDEVICE_DISK_TYPE_AGGREGATED:
		nBindType = NMT_AGGREGATE;
		break;
	case NDAS_UNITDEVICE_DISK_TYPE_RAID1:
		if ( (pUnitDeviceIdGroup->cUnitDevices % 2) != 0 )
			return FALSE;	// ERROR : Number of disks must be even.
		nBindType = NMT_RAID1;
		break;
	// TODO : diskType that has been changed by aingoppa should be applied here.
	default:
		// ERROR : Invalid parameters
		return FALSE;
	}
	
	bResult = IsValidBindDiskCount(nBindType, pUnitDeviceIdGroup->cUnitDevices);
	if ( !bResult )
	{
		// ERROR : Invalid number of disks.
		return FALSE;
	}
	//
	// Create disk objects
	//
	CUnitDiskObjectVector vtUnitDisks;
	CUnitDiskObjectPtr unitDisk;
	UINT i;
	for ( i=0; i < pUnitDeviceIdGroup->cUnitDevices; i++ )
	{
		unitDisk = NdasCreateUnitDiskObject( &pUnitDeviceIdGroup->aUnitDevices[i] );
		if ( unitDisk.get() == NULL )
			return FALSE;
		//
		// Validation of disks
		//
		if ( unitDisk->GetInfoHandler()->IsBound() )
			return FALSE;	// ERROR : disk is already bound.
		vtUnitDisks.push_back(unitDisk);
	}

	//
	// Bind disks
	//
	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		if ( !vtUnitDisks[i]->CanAccessExclusive() )
		{
			// ERROR : cannot access disk exclusively
			return FALSE;
		}
	}

	try {
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Open( TRUE );
		}
	}
	catch ( CNDASException & )
	{
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Close();
		}
		// ERROR : Fail to connect to disk
		return FALSE;
	}

	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		vtUnitDisks[i]->Bind( vtUnitDisks, i, nBindType );
	}

	try {
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->CommitDiskInfo();
		}
	}
	catch ( CNDASException & )
	{
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Close();
		}
		// ERROR : Unexpected error while writing
		return FALSE;
	}
	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		vtUnitDisks[i]->Close();
	}
	return TRUE;
}
コード例 #12
0
ファイル: ndasbind.cpp プロジェクト: yzx65/ndas4windows
BOOL
WINAPI
NdasUnBindUnitDevices(PNDAS_UNITDEVICE_GROUP pUnitDeviceIdGroup)
{
	UINT i;

	CUnitDiskObjectVector vtUnitDisks;
	CUnitDiskObjectPtr unitDisk;
	for ( i=0; i < pUnitDeviceIdGroup->cUnitDevices; i++ )
	{
		unitDisk = NdasCreateUnitDiskObject( &pUnitDeviceIdGroup->aUnitDevices[i] );
		if ( unitDisk.get() == NULL )
			return FALSE;
		//
		// Validation of disks
		//
		if ( !unitDisk->GetInfoHandler()->IsBound() )
			return FALSE; // ERROR : disk is not bound
		vtUnitDisks.push_back(unitDisk);
	}

	//
	// Unbind disks
	//
	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		if ( !vtUnitDisks[i]->CanAccessExclusive() )
		{
			// ERROR : cannot access disk exclusively
			return FALSE;
		}
	}

	try {
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Open( TRUE );
		}
	}
	catch ( CNDASException & )
	{
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Close();
		}
		// ERROR : Fail to connect to disk
		return FALSE;
	}

	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		vtUnitDisks[i]->UnBind( vtUnitDisks[i] );
	}


	try {
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->CommitDiskInfo();
		}
	}
	catch ( CNDASException & )
	{
		for ( i=0; i < vtUnitDisks.size(); i++ )
		{
			vtUnitDisks[i]->Close();
		}
		// ERROR : Unexpected error while writing
		return FALSE;
	}
	for ( i=0; i < vtUnitDisks.size(); i++ )
	{
		vtUnitDisks[i]->Close();
	}
	return TRUE;
}
コード例 #13
0
INT32 CRAID4DiskObject::GetDirtyDisk() const
{
	LAST_WRITTEN_SECTORS Base, Compare;
	BOOL bIsDirty;
	INT32 iDirtyDisk, i;

	if(size() < 3)
		return -1;

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

	bIsDirty = FALSE;
	i = 0;
	iDirtyDisk = -2;

	// checking bitmaps
	for(it = begin(); it != end(); ++it, i++)
	{
		pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);
		if(::IsEmptyDisk(pUnitDisk))
			return -1;

		pUnitDiskHandler = pUnitDisk->GetInfoHandler();
		if(pUnitDiskHandler->IsPeerDirty())
		{
#ifdef RAID_CRITICAL_CHECK
			if(bIsDirty)
				return -1;
#endif
			bIsDirty = TRUE;
			
			iDirtyDisk = (i == 0) ? size() -1 : i -1; // previous device is dirty
		}
	}

	// checking LWS
	// 1 pass
	INT32 iSuspect;
	INT32 nFailCnt;
	i = 0;
	nFailCnt = 0;
	for(it = begin(); it != end(); ++it, i++)
	{
		pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);
		if(::IsEmptyDisk(pUnitDisk))
		{
			return -1;
		}

		pUnitDiskHandler = pUnitDisk->GetInfoHandler();

		if(!i)
		{
			if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Base))
				return -1;

			continue;
		}

		if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Compare))
			return -1;

		if(memcmp(&Base, &Compare, sizeof(Base)))
		{
			nFailCnt++;
			iSuspect = i;
		}
	}

	if(0 == nFailCnt) // all are same
	{
		return iDirtyDisk;
	}
	else if(1 == nFailCnt)
	{
		if(bIsDirty && iSuspect != iDirtyDisk)
#ifdef RAID_CRITICAL_CHECK
			return -1;
#else
			return iDirtyDisk;
#endif
		return iSuspect;
	}
	else if(size() -1 == nFailCnt) // 1st device(0) is the suspect
	{
		iSuspect = 0;
		i = 1;

		for(it = begin(), ++it; it != end(); ++it)
		{
			pUnitDisk = boost::dynamic_pointer_cast<CUnitDiskObject>(*it);
			if(::IsEmptyDisk(pUnitDisk))
			{
				return -1;
			}

			pUnitDiskHandler = pUnitDisk->GetInfoHandler();

			if(1 == i)
			{
				if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Base))
					return -1;

				continue;
			}

			if(!pUnitDiskHandler->GetLastWrittenSectorsInfo(&Compare))
				return -1;

			if(memcmp(&Base, &Compare, sizeof(Base)))
			{
#ifdef RAID_CRITICAL_CHECK
				return -1;
#else
				return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk;
#endif
			}

			i++;
		}

		// all the others are same
		if(bIsDirty && iSuspect != iDirtyDisk)
#ifdef RAID_CRITICAL_CHECK
			return -1;
#else
			return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk;
#endif
		
		return iSuspect;
	}
	else // 2 or more devices are not same
	{
#ifdef RAID_CRITICAL_CHECK
		return -1;
#else
		return (-2 == iDirtyDisk) ? iSuspect : iDirtyDisk;
#endif
	}
}
コード例 #14
0
CDiskObjectPtr 
CDiskObjectBuilder::Build(const CDeviceInfoList listDevice, LPREFRESH_STATUS pFuncRefreshStatus, void *context)
{
	CUnitDiskObjectList listDiskObj;
	CDiskObjectCompositePtr root;
	CUnitDiskObjectList::const_iterator found;

	//
	// Build list of unit disks from the device list
	//
	listDiskObj = BuildDiskObjectList(listDevice, pFuncRefreshStatus, context);

	//
	// Construct structure of disks including aggregation and mirroring
	//
	root = CDiskObjectCompositePtr(new CRootDiskObject());

	while ( !listDiskObj.empty() )
	{
		CUnitDiskObjectPtr disk;
		disk = listDiskObj.front();

		CUnitDiskInfoHandlerPtr pInfoHandler = disk->GetInfoHandler();
			
		if ( !pInfoHandler->IsHDD() )
		{
			listDiskObj.pop_front();
			continue; // Only HDD type disk is supported.(This may be changed later)
		}
		if ( pInfoHandler->IsBound() )
		{
			CDiskLocationVector vtLocation =
				pInfoHandler->GetBoundDiskLocations(disk->GetLocation());

			if(NMT_RAID4 == pInfoHandler->GetNDASMediaType())
			{
				CDiskObjectCompositePtr raid4Disks = 
					CDiskObjectCompositePtr(new CRAID4DiskObject());

				for(UINT i = 0; i < vtLocation.size(); i++)
				{
					found = std::find_if(
						listDiskObj.begin(),
						listDiskObj.end(),
						std::bind1st(CDiskLocationEqual(), vtLocation[i]));

					if(found != listDiskObj.end() && 
						::HasSameBoundDiskList(*found, disk))
					{
						raid4Disks->AddChild(raid4Disks, *found);
						listDiskObj.erase(found);
					}
					else
					{
						raid4Disks->AddChild(raid4Disks,
							::CreateEmptyDiskObject());
					}
				}
				root->AddChild(root, raid4Disks);
			}
			else if ( pInfoHandler->IsBoundAndNotSingleMirrored() )
			{
				CDiskObjectCompositePtr aggrDisks = 
					CDiskObjectCompositePtr(new CAggrDiskObject());

				if ( pInfoHandler->IsMirrored() ) // double tree
				{
					for ( UINT i=0; i < vtLocation.size(); i+= 2 )
					{
						CMirDiskObjectPtr mirDisks =
							CMirDiskObjectPtr( new CMirDiskObject() );

						int emptydisk = 0;

						// find first of the pair
						found = std::find_if( 
								listDiskObj.begin(), 
								listDiskObj.end(),
								std::bind1st(CDiskLocationEqual(), vtLocation[i])
								);
						if ( found != listDiskObj.end() 
							&& ::HasSameBoundDiskList(*found, disk) )
						{
							mirDisks->AddChild( mirDisks, *found );
							listDiskObj.erase(found);
						}
						else
						{
							// create empty unit disk
							emptydisk++;
						}

						// find second of the pair
						found = std::find_if( 
							listDiskObj.begin(), 
							listDiskObj.end(),
							std::bind1st(CDiskLocationEqual(), vtLocation[i+1])
							);

						if ( found != listDiskObj.end() 
							&& ::HasSameBoundDiskList(*found, disk) )
						{
							mirDisks->AddChild( mirDisks, *found );
							listDiskObj.erase(found);
						}
						else
						{
							// create empty unit disk
							emptydisk++;
						}

						if(0 == emptydisk)
						{
						}
						else if(1 == emptydisk)
						{
							mirDisks->AddChild( mirDisks, ::CreateEmptyDiskObject());
						}
						else
						{
							listDiskObj.pop_front();
							root->AddChild( root, disk );
							break;
						}

						if ( mirDisks->size() != 0 ) // always 2 including empty disks
							aggrDisks->AddChild( aggrDisks, mirDisks );
					}
				}
				else
				{
					BOOL bFound = FALSE, bFoundSelf = FALSE;
					for ( UINT i=0; i < vtLocation.size(); i++ )
					{
						CDiskLocationPtr p = vtLocation[i];
						found = std::find_if( 
							listDiskObj.begin(), 
							listDiskObj.end(),
							std::bind1st(CDiskLocationEqual(), vtLocation[i])
							);
						if ( found != listDiskObj.end()
							&& ::HasSameBoundDiskList(*found, disk) )
						{
							bFound = TRUE;

							if(*found == disk)
								bFoundSelf = TRUE;

							aggrDisks->AddChild( aggrDisks, *found );
							listDiskObj.erase(found);
						}
						else
						{
							// create empty unit disk
							aggrDisks->AddChild( aggrDisks, ::CreateEmptyDiskObject());
						}

					}

					if(!bFound)
					{
						listDiskObj.pop_front();
						root->AddChild( root, disk );
						break;
					}

					if(!bFoundSelf)
					{
						listDiskObj.pop_front();
						root->AddChild( root, disk );
					}
				}
				root->AddChild( root, aggrDisks );
			}
			else if ( pInfoHandler->IsMirrored() )
			{
				CMirDiskObjectPtr mirDisks =
					CMirDiskObjectPtr( new CMirDiskObject() );

				UINT i = 0;
				int emptydisk = 0;

				// find first of the pair
				found = std::find_if( 
					listDiskObj.begin(), 
					listDiskObj.end(),
					std::bind1st(CDiskLocationEqual(), vtLocation[i])
					);
				if ( found != listDiskObj.end() 
					&& ::HasSameBoundDiskList(*found, disk) )
				{
					mirDisks->AddChild( mirDisks, *found );
					listDiskObj.erase(found);
				}
				else
				{
					// create empty unit disk
					emptydisk++;
				}

				// find second of the pair
				found = std::find_if( 
					listDiskObj.begin(), 
					listDiskObj.end(),
					std::bind1st(CDiskLocationEqual(), vtLocation[i+1])
					);
				if ( found != listDiskObj.end() 
					&& ::HasSameBoundDiskList(*found, disk) )
				{
					mirDisks->AddChild( mirDisks, *found );
					listDiskObj.erase(found);
				}
				else
				{
					// create empty unit disk
					emptydisk++;
				}

				if(0 == emptydisk)
				{
				}
				else if(1 == emptydisk)
				{
					mirDisks->AddChild( mirDisks, ::CreateEmptyDiskObject());
				}
				else
				{
					listDiskObj.pop_front();
					root->AddChild( root, disk );
					break;
				}

				root->AddChild(root, mirDisks);
			}
			else
			{
				listDiskObj.pop_front();
				root->AddChild( root, disk );
			}
		}
		else // pDiskInfoHander->IsBound()
		{
			listDiskObj.pop_front();
			root->AddChild( root, disk );
		}
	}	// while ( !listDiskObj.empty() )
	return root;
}