// BMAFImp.cpp: implementation of the CBMAFImp class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"

#include <atlconv.h>
#include <initguid.h>
#include <dbt.h>

#pragma warning(push,3)
#include <vector>
#include <algorithm>
#pragma warning(pop)

#include "BMAFImp.h"
#include "BMAFrame.h"
#include "XmlConfigParse.h"
#include "BootModeguid.h"
#include "BMFile.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////
/////////////////////////////////////////////////////

//#define  NEW_TD_DLOADER

#ifdef NEW_TD_DLOADER
#define ADD_DOWNLOAD_LENGTH       512
#else
#define ADD_DOWNLOAD_LENGTH       8
#endif

//#define MAX_RET_FILE_NUM 5

static BOOL GetAbsolutePath(CString &strAbsoluteFilePath,LPCTSTR lpszFilePath )
{
    TCHAR szFileName[_MAX_FNAME];    
    TCHAR szDir[_MAX_DIR];
    TCHAR szDirve[_MAX_DRIVE];	
    
    _tsplitpath( lpszFilePath,szDirve,NULL,NULL,NULL);	
    if( szDirve[0] == _T('\0') )
	{//do it if strHelpTopic is ralatively 
        GetModuleFileName( AfxGetApp()->m_hInstance, szFileName,_MAX_FNAME);
        _tsplitpath( szFileName , szDirve , szDir , NULL , NULL );	
        strAbsoluteFilePath = szDirve;
        strAbsoluteFilePath += szDir;
        if( lpszFilePath[0] == _T('\\') || lpszFilePath[0] == _T('/') )
            lpszFilePath++;
        
        strAbsoluteFilePath += lpszFilePath;		
    }
	else
	{
        strAbsoluteFilePath = lpszFilePath;
    }
    return true;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CBMAFImp::CBMAFImp()
{
	m_arrFile.RemoveAll();
	m_strProductName.Empty();
	m_pOpenArgument = 0;
	m_arrFileInfo.clear();
	
	m_nFileCount = 0 ;
	m_nBMFileCount = 0;
	m_arrBMFileInfo.clear();
	m_mapObserverRegs.RemoveAll();
	m_bInitBMFiles = FALSE;

	m_dwWaitTime = 0;
	m_dwRepartitionFlag = 1;
    m_bLog = HasLog();
	m_strSpecConfig = _T("");

	m_dwReadFlashBRFlag = 0;

    m_strFileType = _T("");

	m_dwPacketLength = 0x1000;

	m_arrBMFileInfoEx.clear();

	if(m_bLog)
	{
		m_bLog = StartLog();
	}
}

CBMAFImp::~CBMAFImp()
{

}
/**
 * stop one port work
 *
 * @param lpszProductName: the product name; 
 * @param ppszFileList: the download files; 
 * @param dwFileCount: the number of download files; 
 * @param pOpenArgument: the download channel(port) param;
 * @param bBigEndian: if bigendian; 
 * @param dwOprCookie: the port identify;
 * @param bRcvThread: 
 * @param pReceiver: 
 * @param lpbstrProgID: 
 *
 * @return Returns S_OK if successful,Otherwise returns error code;
 */ 
HRESULT CBMAFImp::BMAF_StartOneWork(LPCTSTR lpszProductName, 
									LPCTSTR *ppszFileList,
									DWORD  dwFileCount,
									DWORD  pOpenArgument,
									BOOL bBigEndian, 
									DWORD dwOprCookie,
									BOOL bRcvThread, 
									const DWORD pReceiver,
									BSTR lpbstrProgID )
{
	if(m_bLog && !m_log.IsOpenLog())
	{
		if(!StartLog())
			return BMAF_E_STRART_LOG_FAIL;
	}

//     if( FAILED( CoInitialize(NULL) ) )
//     {
// 		if(m_bLog && m_log.IsOpenLog())
// 			m_log.XLog(_T("COM Initialize Failed"));
// 		return BMAF_E_COM_INIT_FAIL;
// 	}

	if(!RegBootModeObj(dwOprCookie))
		return BMAF_E_REG_BMOBJ_FAIL;

	if(!RegBMPObserver(dwOprCookie))
		return BMAF_E_REG_BMPOBSERVER_FAIL;

	m_strProductName = lpszProductName;
	m_arrFile.RemoveAll();

	for(UINT i= 0;i< dwFileCount;i++)
		m_arrFile.Add(ppszFileList[i]);

	m_nFileCount = (UINT) dwFileCount;
	m_pOpenArgument = pOpenArgument;


    if(!m_bInitBMFiles)
	{
      if(!InitBMFiles(dwOprCookie))
		  return BMAF_E_INIT_BMFILES_FAIL;
	  m_bInitBMFiles = TRUE;
	}
	if(m_nBMFileCount == 0)
		return S_OK;

	return StartOneWork(bBigEndian, 
						dwOprCookie,
						bRcvThread, 
						pReceiver,
						lpbstrProgID );
	
	

}

/**
 * stop all port work
 *
 * @return Returns S_OK if successful,Otherwise returns S_FAIL;
 */ 
HRESULT CBMAFImp::BMAF_StopAllWork()
{
    POSITION pos = m_mapBootModeObj.GetStartPosition();
    DWORD dwCookie = 0;
	
    PBOOTMODEOBJ_T  pStruct = NULL;
    while( pos )
    {
        m_mapBootModeObj.GetNextAssoc( pos, dwCookie, pStruct );

        pStruct->pSnapin->StopBootModeOperation();
        IBMOprSubscriber* pSubscriber;
        HRESULT hr = pStruct->pSnapin->QueryInterface( IID_IBMOprSubscriber, (LPVOID*)&pSubscriber );
        if( SUCCEEDED( hr ) )
        {
            pSubscriber->UnsubscribeOperationObserver( pStruct->dwCookie );
        }

        pStruct->pSnapin->Release();
        delete pStruct;
    }
	
    m_mapBootModeObj.RemoveAll();
	ClearBMFiles();	

	m_arrFile.RemoveAll();
	m_nFileCount =0;
    
	int nCount = m_arrFileInfo.size();
	for(int i=0;i<nCount;i++)
	{
		delete [] m_arrFileInfo[i];
	}
	m_arrFileInfo.clear();


	m_bInitBMFiles = FALSE;
	
	StopLog();

	return S_OK;
}

/**
 * stop one port work
 *
 * @param dwOprCookie: the port identify; 
 *
 * @return Returns S_OK if successful,Otherwise returns S_FAIL;
 */ 
HRESULT CBMAFImp::BMAF_StopOneWork( DWORD dwOprCookie )
{
	PBOOTMODEOBJ_T pBMO = NULL;
	HRESULT hr;
	hr = BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pBMO);
	if(FAILED(hr))
		return hr;

	if( !pBMO->bStop )
    {        
        pBMO->pSnapin->StopBootModeOperation();
        
        IBMOprSubscriber * pSubscriber;
        hr = pBMO->pSnapin->QueryInterface( IID_IBMOprSubscriber, (LPVOID*)&pSubscriber );
        if( SUCCEEDED( hr ) )
        {
            pSubscriber->UnsubscribeOperationObserver( pBMO->dwCookie );
        }        
        pBMO->bStop = TRUE;
    }
	return S_OK;
}

/**
 * Get struct BOOTMODEOBJ_T information
 *
 * @param dwOprCookie: the port identify; 
 * @param ppBootModeObjT: the pointer of struct BOOTMODEOBJ_T
 *
 * @return Returns S_OK if successful,Otherwise returns S_FAIL;
 */   
HRESULT CBMAFImp::BMAF_GetBootModeObjInfo(DWORD dwOprCookie, LPDWORD ppBootModeObjT)
{
	PBOOTMODEOBJ_T pBMO = NULL;
	if(m_mapBootModeObj.Lookup(dwOprCookie,pBMO))
		*ppBootModeObjT = (DWORD)pBMO;
	else
		*ppBootModeObjT = 0;

	return S_OK;
}

/**
 * Register BootmodePlatform DLL
 *
 * @param lpszDllName: DLL name; 
 *
 * @return Returns S_OK if successful,Otherwise returns error code;
 */   
HRESULT CBMAFImp::BMAF_RegisterBMPDll(LPCTSTR lpszDllName)
{
	UNREFERENCED_PARAMETER(lpszDllName);
/*	CString strErrMsg;
	if(m_bLog && !m_log.IsOpenLog())
		StartLog();
	
	BOOL bRegSuccess = TRUE;
    HRESULT hr = OleInitialize( NULL );
    if( SUCCEEDED(hr) )
    {
        HINSTANCE hLib = LoadLibrary( lpszDllName );
		
        if ( hLib >= (HINSTANCE)HINSTANCE_ERROR)
        {
            FARPROC lpDllEntryPoint = NULL;
            // Find the entry point.
            (FARPROC&)lpDllEntryPoint = GetProcAddress( hLib, "DllRegisterServer");
            if(lpDllEntryPoint != NULL)
            {
                hr = (*lpDllEntryPoint)();
                if( FAILED( hr ) )
                {
					if(m_bLog && m_log.IsOpenLog())
					{
						strErrMsg.Format( _T("Call DllRegisterServer fail (%s).[ErrorCode:0x%08X]"), lpszDllName,hr );
						m_log.XLog( strErrMsg );
					}
					bRegSuccess = FALSE;
                }
            }
            else
            {
				 if(m_bLog && m_log.IsOpenLog())
				 {
					 strErrMsg.Format(_T("Get process address  fail %s."),lpszDllName);
					 m_log.XLog( strErrMsg );
				 }
				 bRegSuccess = FALSE;
            }            
        }
        else
        {
			if(m_bLog && m_log.IsOpenLog())
			{
				strErrMsg.Format(_T("Load %s fail."),lpszDllName);
				m_log.XLog( strErrMsg );
			}
			bRegSuccess = FALSE;
        }
		
        OleUninitialize( );	 
		if(!bRegSuccess)
			return BMAF_E_REG_DLL_FAIL;
    }
    else
    {
		if(m_bLog && m_log.IsOpenLog())
		{
			strErrMsg = _T("Call OleInitialize() fail.");
			m_log.XLog( strErrMsg );
		}
        return BMAF_E_COM_INIT_FAIL;
    }*/
	return S_OK;
}
/**
 * Unregister BootmodePlatform DLL,not implement
 *
 * @param lpszDllName: DLL name; 
 *
 * @return Returns S_OK if successful,Otherwise returns error code;
 */   
HRESULT CBMAFImp::BMAF_UnregisterBMPDll(LPCTSTR lpszDllName)
{
	UNUSED_ALWAYS(lpszDllName);
	return S_OK;
}

/**
 * Subscribe Callback observer
 *
 * @param dwOprCookie: the port identify; 
 * @param pSink: pointer of IBMOprObserver; 
 * @param uFlags: not used for extent future; 
 *
 * @return Returns S_OK ;
 */  
HRESULT CBMAFImp::BMAF_SubscribeObserver(THIS_ DWORD dwOprCookie,
										THIS_ IBMOprObserver* pSink, 
									    ULONG uFlags)

{
	UNUSED_ALWAYS(uFlags);

    CSingleLock _lock( &m_CS, TRUE);
	IBMOprObserver* pBMOprObs = NULL;
	if( m_mapObserverRegs.Lookup( dwOprCookie, pBMOprObs) )
	{
        return S_OK;   // already subscribe 
    }

	m_mapObserverRegs.SetAt( dwOprCookie, pSink );
    pSink->AddRef();


    if(m_bLog && !m_log.IsOpenLog())
	    StartLog();
	if(m_bLog && m_log.IsOpenLog())
	{
		CString strMsg;
		strMsg.Format(_T("[PORT:%d] Subscribe Operation Observer succeed."),dwOprCookie);
		m_log.XLog( strMsg );
	}
	return S_OK;
}
/**
 * Unsubscribe Callback observer
 *
 * @param dwOprCookie: the port identify; 
 *
 * @return Returns S_OK;
 */  
HRESULT CBMAFImp::BMAF_UnsubscribeObserver(THIS_ DWORD dwOprCookie)
{
	CSingleLock _lock( &m_CS, TRUE);
	
    IBMOprObserver* pObserver;
    if( !m_mapObserverRegs.Lookup( dwOprCookie, pObserver ) )
        return BM_E_FAILED;
	
    pObserver->Release();
    m_mapObserverRegs.RemoveKey( dwOprCookie );
    //Log( "Unsubscribe Operation Observer.");
	return S_OK;
}
/**
 * Set property for download
 *
 * @param dwPropertyID: the property identify;
 * @param dwPropertyValue: the property value; 
 *
 * @return Returns S_OK if successful,Otherwise returns S_FALSE;
 */  
HRESULT CBMAFImp::BMAF_SetProperty(DWORD dwPropertyID, DWORD dwPropertyValue)
{
	switch(dwPropertyID) {
	case BMAF_TIME_WAIT_FOR_NEXT_CHIP:
		m_dwWaitTime = dwPropertyValue;
		break;
	case BMAF_NAND_REPARTION_FLAG:
		m_dwRepartitionFlag = dwPropertyValue;
		break;
	case BMAF_SPECIAL_CONFIG_FILE:
		m_strSpecConfig = (LPCTSTR)dwPropertyValue;
		break;
	case BMAF_READ_FLASH_BEFORE_REPARTITION:
		m_dwReadFlashBRFlag = dwPropertyValue;
		break;
	case BMAF_SPEC_FILE_TYPE:
		m_strFileType  = (LPCTSTR)dwPropertyValue;
		break;
	default:
		return S_FALSE;
		break;
	}	

	return S_OK;
}
/**
 * Get property for download
 *
 * @param dwPropertyID: the property identify;
 * @param dwPropertyValue: the property value to store; 
 *
 * @return Returns S_OK if successful,Otherwise returns S_FALSE;
 */ 
HRESULT CBMAFImp::BMAF_GetProperty(DWORD dwPropertyID, LPDWORD lpdwPropertyValue)
{
	switch(dwPropertyID) {
	case BMAF_TIME_WAIT_FOR_NEXT_CHIP:
		*lpdwPropertyValue = m_dwWaitTime;
		break;
	case BMAF_NAND_REPARTION_FLAG:
		*lpdwPropertyValue = m_dwRepartitionFlag;
		break;
	case BMAF_SPECIAL_CONFIG_FILE:
		*lpdwPropertyValue = (DWORD)(LPCTSTR)m_strSpecConfig;
		break;
	case BMAF_READ_FLASH_BEFORE_REPARTITION:
		*lpdwPropertyValue = m_dwReadFlashBRFlag;
		break;
	case BMAF_SPEC_PACKET_LENGTH:
        *lpdwPropertyValue = m_dwPacketLength;
		break;
	default:
		return S_FALSE;
		break;
	}	
	
	return S_OK;
}
/**
 * Set Communicate channel pointer
 *
 * @param dwOprCookie: the port identify;
 * @param pCommunicateChannel: Communicate channel pointer; 
 *
 * @return Returns S_OK if successful,Otherwise returns S_FALSE;
 */ 
HRESULT CBMAFImp::BMAF_SetCommunicateChannelPtr(DWORD dwOprCookie,
												LPVOID pCommunicateChannel )
{
    PBOOTMODEOBJ_T pBMO = NULL;
	BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pBMO);
	if(NULL == pBMO)
		return S_FALSE;
	return pBMO->pSnapin->SetCommunicateChannelPtr(pCommunicateChannel);
}
/**
 * Get Communicate channel pointer
 *
 * @param dwOprCookie: the port identify;
 * @param pCommunicateChannel: Communicate channel pointer; 
 *
 * @return Returns S_OK if successful,Otherwise returns S_FALSE;
 */ 
HRESULT CBMAFImp::BMAF_GetCommunicateChannelPtr(DWORD dwOprCookie, 
												/*[out]*/LPVOID* ppCommunicateChannel )
{
    PBOOTMODEOBJ_T pBMO = NULL;
	BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pBMO);
	if(NULL == pBMO)
		return S_FALSE;
	return pBMO->pSnapin->GetCommunicateChannelPtr(ppCommunicateChannel);
}
/**
 * Release this
 *
 * @return Returns S_OK;
 */ 
HRESULT CBMAFImp::BMAF_Release()
{
	delete this;
	return S_OK;
}
/////////////////////////////////////////////////////

HRESULT CBMAFImp::StartOneWork(BOOL bBigEndian, 
						 DWORD dwOprCookie,
						 BOOL bRcvThread, 
						 const DWORD pReceiver,
						 BSTR lpbstrProgID )
{
    HRESULT hr = 0;
	IBootModeHandler* pBootModehandler =m_pBootModeObj->pSnapin;
    IBMSettings * pSettings = NULL;
    hr = pBootModehandler->QueryInterface( IID_IBMSettings, (LPVOID*)&pSettings );
    if( SUCCEEDED( hr ) )
    {
        // Set repartition flags,only used by nand flash
        pSettings->SetRepartitionFlag( m_dwRepartitionFlag );
        
		pSettings->SetReadFlashBefRepFlag( m_dwReadFlashBRFlag );

		VARIANT varValue;
		varValue.bstrVal = T2OLE((LPTSTR)(LPCTSTR)m_strProductName);
		
		pSettings->SetProperty(0,_T("PRODUCT"), &varValue);

		if(!m_strFileType.IsEmpty())
		{
			m_dwPacketLength = pSettings->GetPacketLength( T2OLE((LPTSTR)(LPCTSTR)m_strFileType) );
		}
		else
		{
			m_dwPacketLength = 0x1000;
		}
    }

	BMFileInfo *pBMFileInfo = new BMFileInfo[m_nBMFileCount];
	if(pBMFileInfo == NULL)
		return BMAF_E_OUTOFMEMORY;
	memset(pBMFileInfo,0,m_nBMFileCount*sizeof(BMFileInfo));
	for(UINT i=0;i<m_nBMFileCount;i++)
	{
		memcpy(pBMFileInfo+i,m_arrBMFileInfo[i],sizeof(BMFileInfo));
	}
	
    hr = pBootModehandler->StartBootModeOperation( (DWORD)pBMFileInfo, 
											(DWORD)m_nBMFileCount,
											m_pOpenArgument, 
											bBigEndian, 
											dwOprCookie,
											bRcvThread, 
											pReceiver,
											lpbstrProgID );

	if(SUCCEEDED( hr ))
	{
		pBootModehandler->SetWaitTimeForNextChip( m_dwWaitTime );
	}
	else
	{
		UnregBMPObserver(dwOprCookie);
	}

	delete []pBMFileInfo;

	if(m_pBootModeObj != NULL)
		m_pBootModeObj->bStop = FALSE;
    
	return hr;
}


//////////////////////////////////////////////
BOOL CBMAFImp::InitBMFiles(DWORD dwOprCookie)
{
    USES_CONVERSION;
	
	if(m_nFileCount == 0)
		return TRUE;		

	CXmlConfigParse *pXCP = new CXmlConfigParse;

	_TCHAR szConfigFile[MAX_PATH];
	GetModuleFilePath( /*_Module.GetModuleInstance()*/AfxGetInstanceHandle(), szConfigFile );
	_tcscat( szConfigFile,  _T("\\BMAConfig.xml") );	
	
	if( !pXCP->Init(szConfigFile))
	{
		if(m_bLog && m_log.IsOpenLog())
		{
			m_log.XLog(_T("Read \"BMAConfig.xml\" file failed!"));
		}
		pXCP->Release();
		pXCP = NULL;
		return FALSE;
	}
	
	if(!m_strSpecConfig.IsEmpty())
	{
		if( !pXCP->Init(m_strSpecConfig,1))
		{
			if(m_bLog && m_log.IsOpenLog())
			{
				m_log.XLog(_T("Read xml configure file failed!"));
			}
			pXCP->Release();
			pXCP = NULL;
			return FALSE;
		}
	}

	UINT nCount =0;
	UINT nRealCount = 0;
	UINT i=0;

	PFILE_INFO_T pFileInfo = NULL;
	PPRODUCT_INFO_T pProd = NULL;
	pProd = pXCP->GetProdInfo(m_strProductName);
	nCount = pProd->dwFileCount;
	for(i=0;i<nCount;i++)
	{
		pFileInfo = new FILE_INFO_T;
		memcpy(pFileInfo,pProd->pFileInfoArr + i,sizeof(FILE_INFO_T));
		if(pFileInfo->dwFlag != FILE_OMIT_FALG)
		{
			m_arrFileInfo.push_back(pFileInfo);
			++nRealCount;
		}
		else
		{
			delete pFileInfo;
			pFileInfo = NULL;
		}
	}

	m_nBMFileCount = nRealCount;
	pXCP->Release();
	pXCP = NULL;

	//输入的文件个数应该与配置文件的个数减去忽略的文件后的个数相同	
	if(m_nFileCount != m_nBMFileCount )
	{
		if(m_bLog && m_log.IsOpenLog())
			m_log.XLog(_T("The number of input files not match the number of files in xml config minusing the omitting files "));
		return FALSE;
	}
	
	nCount =0;
	i=0;
	
	IBMOprObserver *pObserver;	

	
    pFileInfo = NULL;
	BMFileInfo * pBMFileInfoArr = new BMFileInfo[MAX_RET_FILE_NUM];
	memset(pBMFileInfoArr,0,MAX_RET_FILE_NUM * sizeof(BMFileInfo));
	BMFileInfo * pBMFileInfo = NULL;
	DWORD dwBMFileInfoCount = 0;
	DWORD dwFlag = 0;

	BOOL bOK = TRUE;

	for( i = 0; i<m_nFileCount;i++)
	{
		pFileInfo = m_arrFileInfo[i];
        pBMFileInfo = NULL;
		memset(pBMFileInfoArr,0,MAX_RET_FILE_NUM * sizeof(BMFileInfo));
		dwBMFileInfoCount = 0;
		dwFlag = 0;
		//从GUI上忽略的文件
		if(m_arrFile[i].CompareNoCase(FILE_OMIT) == 0)
		{
			continue;
		}
		
		if( m_mapObserverRegs.Lookup(dwOprCookie,pObserver))
		{
			HRESULT hr = pObserver->OnFilePrepare(dwOprCookie,
				T2OLE((LPTSTR)(LPCTSTR)m_strProductName),
				T2OLE((LPTSTR)(LPCTSTR)m_arrFile[i]),
				(DWORD)pFileInfo,
				(DWORD)pBMFileInfoArr,
				&dwBMFileInfoCount,
				&dwFlag);
			if(FAILED(hr))
			{
				if(m_bLog && m_log.IsOpenLog())
					m_log.XLog(_T("OnFilePrepare: Failed\n "));
				bOK = FALSE;
				break;				
			}
			if(dwFlag)  //回调已经处理，dwBMFileInfoCount 反映处理的情况
			{
				for(UINT j = 0; j<dwBMFileInfoCount; j++ )
				{
					pBMFileInfo = new BMFileInfo;
					memcpy(pBMFileInfo,pBMFileInfoArr+j,sizeof(BMFileInfo));
					m_arrBMFileInfo.push_back(pBMFileInfo);
					nCount++;
				}
			}
		}
		
		if(dwFlag == 0)
		{
			pBMFileInfo = new BMFileInfo;
			InitBMFileDefault(pBMFileInfo,i);
			m_arrBMFileInfo.push_back(pBMFileInfo);
			nCount++;
		}		
	}
   
	if(!bOK)
	{
		m_nBMFileCount = nCount;
		delete [] pBMFileInfoArr;
		ClearBMFiles();
		return bOK;
	}

	// do extend files
	{
		bOK = TRUE;
		pBMFileInfo = NULL;
		memset(pBMFileInfoArr,0,MAX_RET_FILE_NUM * sizeof(BMFileInfo));
		dwBMFileInfoCount = 0;
		dwFlag = 0;			
		if( m_mapObserverRegs.Lookup(dwOprCookie,pObserver))
		{
			HRESULT hr = pObserver->OnFilePrepare(dwOprCookie,
				T2OLE((LPTSTR)(LPCTSTR)m_strProductName),
				NULL,
				0,
				(DWORD)pBMFileInfoArr,
				&dwBMFileInfoCount,
				&dwFlag);
			if(FAILED(hr))
			{
				if(m_bLog && m_log.IsOpenLog())
					m_log.XLog(_T("OnFilePrepare: Failed\n "));
				bOK = FALSE;					
			}
			if(bOK && dwFlag)  //回调已经处理，dwBMFileInfoCount 反映处理的情况
			{
				for(UINT j = 0; j<dwBMFileInfoCount; j++ )
				{
					pBMFileInfo = new BMFileInfo;
					memcpy(pBMFileInfo,pBMFileInfoArr+j,sizeof(BMFileInfo));
					m_arrBMFileInfo.push_back(pBMFileInfo);
					nCount++;
				}				
			}
		}		
	}

	m_nBMFileCount = nCount;
	delete [] pBMFileInfoArr;

	if(!bOK)
	{
		ClearBMFiles();
	}

	return bOK;

/*   // Open file mapping objects
    for( i=0; i < m_nBMFileCount; i++)
    {
        if( !LoadBMFileInfo( m_arrBMFileInfo[i] ) )
        {
            ClearBMFiles();

			CString strErr;
			strErr.Format("Load BMFile[%s] failed",m_arrBMFileInfo[i]->szFileID);
			m_log.XLog(strErr);
			
            return FALSE;
        }
        if(  i + 1  < m_nBMFileCount &&
            stricmp( m_arrBMFileInfo[ i ]->szFileType, "TDCODE") == 0 &&
            stricmp( m_arrBMFileInfo[ i + 1 ]->szFileType, "TDCODE") == 0 )
        {
            DWORD dwAddrValue = m_arrBMFileInfo[i + 1 ]->dwBase - 0x20000000;
            DWORD dwAddrValueEndian =   dwAddrValue << 24
                | ( (dwAddrValue & 0x0000FF00) >> 8 ) << 16
                | ( (dwAddrValue & 0x00FF0000) >> 16 ) << 8
                | dwAddrValue >> 24;
            memcpy(  (LPBYTE)(m_arrBMFileInfo[ i ]->lpCode) + 4 , (LPBYTE)&dwAddrValueEndian, 4 );            
        }
    }*/
//	return TRUE;
	
}
void CBMAFImp::InitBMFileDefault(PBMFileInfo lpBMFileInfo, int nFileIndex)
{
	ASSERT(lpBMFileInfo != NULL);

    FILE_INFO_T * pFileInfo = NULL;
	pFileInfo = m_arrFileInfo[nFileIndex];

	memset(lpBMFileInfo,0,sizeof(BMFileInfo));
	_tcscpy(lpBMFileInfo->szFileID,pFileInfo->szID);
	_tcscpy(lpBMFileInfo->szFileType,pFileInfo->szType);
	_tcscpy(lpBMFileInfo->szFileName,m_arrFile[nFileIndex]);
	
	lpBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
	
	if(pFileInfo->dwFlag == 0/*_tcsicmp( lpBMFileInfo->szFileID, _T("FLASH") )==0*/)
	{
		lpBMFileInfo->bLoadCodeFromFile = FALSE;
		lpBMFileInfo->dwOprSize = pFileInfo->arrBlock[0].dwSize;
	}
	else
	{
		lpBMFileInfo->bLoadCodeFromFile = TRUE;
		lpBMFileInfo->dwCodeSize = pFileInfo->arrBlock[0].dwSize;
	}
}

BOOL CBMAFImp::RegBootModeObj(DWORD dwOprCookie)
{
    HRESULT hr = 0;    
	
    if( m_mapBootModeObj.Lookup(dwOprCookie, m_pBootModeObj) )
    {		
        m_pBootModeObj->bStop         = TRUE;
        m_pBootModeObj->bFirstStart   = FALSE;
    }
    else
    {
		m_pBootModeObj = new BOOTMODEOBJ_T;
		memset(m_pBootModeObj,0,sizeof(BOOTMODEOBJ_T));     
		IUnknown * pIUn = NULL;
		if(!CreateBMObject(&pIUn))
		{
			if(m_bLog)
			    m_log.XLog(_T("Create BMObject failed."));
            return FALSE; //BMA_ERR_NOTREG
		}
		IBootModeHandler * pBootModeHandler  = NULL;
		hr = pIUn->QueryInterface(IID_IBootModeHandler,(LPVOID*)&pBootModeHandler);
		if(FAILED(hr))
		{
			if(m_bLog)
			    m_log.XLog(_T("IBootModeHandler is not implemented"));
            return FALSE; //BMA_ERR_NOTREG
		}

		pBootModeHandler->AddRef();      
		//m_pBootModeObj->clsid = clsidHandler;
		m_pBootModeObj->pSnapin = pBootModeHandler;
		m_pBootModeObj->bStop = FALSE;
		m_pBootModeObj->dwCookie = 0; //没有注册Observer
		m_pBootModeObj->bFirstStart = TRUE;

		m_mapBootModeObj.SetAt(dwOprCookie,m_pBootModeObj);
    }
	if(m_bLog && m_log.IsOpenLog())
	{
		CString str;
		str.Format(_T("[PORT:%d] Register BootModeObj succeed."),dwOprCookie);
		m_log.XLog(str);
	}
	return TRUE;

}

BOOL CBMAFImp::UnregBootModeObj(DWORD dwOprCookie)
{
	
	if(!m_mapBootModeObj.Lookup(dwOprCookie,m_pBootModeObj))
	{
		return FALSE;
	}
	delete m_pBootModeObj;
	m_pBootModeObj = NULL;
	m_mapBootModeObj.RemoveKey(dwOprCookie);
	return TRUE;
}
BOOL CBMAFImp::RegBMPObserver(DWORD dwOprCookie)
{
	IBMOprObserver* pObserver=NULL;
	IBMOprSubscriber * pSubscriber = NULL;
	if(!m_mapObserverRegs.Lookup(dwOprCookie,pObserver))
		return TRUE;
	DWORD dwCookie = 0;
	IBootModeHandler * pbmh = m_pBootModeObj->pSnapin;
	HRESULT hr = pbmh->QueryInterface( IID_IBMOprSubscriber, (LPVOID*)&pSubscriber );
    
	if( SUCCEEDED( hr ) )
	{
	    hr = pSubscriber->SubscribeOperationObserver( pObserver, NULL, &dwCookie );
		if(FAILED( hr ) )
		{
			if(m_bLog)
			{
				CString str;
				str.Format(_T("Subscribe operation observer failed.[ErrorCode:0x%08X]"),hr);
				m_log.XLog(str);
			}
			return FALSE;
		}
		PBOOTMODEOBJ_T pBootModeObj = NULL;
		m_mapBootModeObj.Lookup(dwOprCookie,pBootModeObj);
		ASSERT(pBootModeObj !=NULL);
		pBootModeObj->dwCookie = dwCookie; //表明注册
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
BOOL CBMAFImp::UnregBMPObserver(DWORD dwOprCookie)
{
	PBOOTMODEOBJ_T pBMO = NULL;
	if(FAILED(BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pBMO)))
		return FALSE;
		
	IBMOprSubscriber *pSubscriber = NULL;
	
	HRESULT hr = pBMO->pSnapin->QueryInterface( IID_IBMOprSubscriber, (LPVOID*)&pSubscriber );
    
	if( SUCCEEDED( hr ) )
	{
		pSubscriber->UnsubscribeOperationObserver( pBMO->dwCookie );
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

BOOL CBMAFImp::StartLog( void )
{	
    return m_log.OpenLog();
}

void CBMAFImp::StopLog( void )
{
    m_log.CloseLog();
}

// BOOL CBMAFImp::LoadBMFileInfo(PBMFileInfo lpBMFileInfo)
// {
//     if( lpBMFileInfo == NULL )
//         return FALSE;
//     
//     if( FALSE == lpBMFileInfo->bLoadCodeFromFile )
//     {
//         return TRUE;
//     }
//     
//     CString strFDLFileName;
//     GetAbsolutePath( strFDLFileName,(LPCTSTR)lpBMFileInfo->szFileName );
//     if( strFDLFileName.IsEmpty() )
//     {
//         return FALSE;
//     }
//     CString strMapName = strFDLFileName ;
//     strMapName.Replace('\\','.');
//     strMapName = "Local\\" + strMapName;
//     
//     HANDLE hFDLCode = INVALID_HANDLE_VALUE;
//     HANDLE hFDLCodeMapView = NULL;
//     
//     hFDLCode = CreateFile(strFDLFileName.operator LPCTSTR (),
//         GENERIC_READ,
//         FILE_SHARE_READ,                         //Exclusive Open
//         NULL,                      //Can't Be inherited
//         OPEN_EXISTING,             //If not existing then failed
//         FILE_ATTRIBUTE_READONLY,   //Read Only
//         NULL);
//     if( hFDLCode == INVALID_HANDLE_VALUE)
//     {   
//         return FALSE;
//     }
//     
//     DWORD dwFDLCodeSize = GetFileSize( hFDLCode, NULL);
//     if( dwFDLCodeSize == INVALID_FILE_SIZE)
//     {
//         CloseHandle( hFDLCode);
//         return FALSE;
//     }
//     
//     hFDLCodeMapView = CreateFileMapping( hFDLCode,   //The Handle of Opened File
//         NULL,          //Security
//         PAGE_READONLY, //Read Only Access
//         0,             //Max Size
//         0,             //Min Size
//         strMapName);   //Object Name
//     
//     if( hFDLCodeMapView == NULL)
//     {
//         CloseHandle( hFDLCode);
//         return FALSE;
//     }
//     
//     void* lpCode = ::MapViewOfFile( hFDLCodeMapView, FILE_MAP_READ,  0, 0, 0);    
//     if( lpCode == NULL)
//     {
//         CloseHandle( hFDLCode );
//         CloseHandle( hFDLCodeMapView );
//         return FALSE;
//     }      
//     
//     lpBMFileInfo->dwCodeSize = dwFDLCodeSize;
//     if( _tcsicmp( lpBMFileInfo->szFileType, _T("TDCODE") ) == 0 )
//     {
//         lpBMFileInfo->bChangeCode = TRUE;
//         lpBMFileInfo->lpCode = new BYTE[ dwFDLCodeSize + ADD_DOWNLOAD_LENGTH ];
//         memset( lpBMFileInfo->lpCode, 0xFF, ADD_DOWNLOAD_LENGTH );   
//         
//         DWORD dwSizeValueEndian =   dwFDLCodeSize << 24
//             | ( (dwFDLCodeSize & 0x0000FF00) >> 8 ) << 16
//             | ( (dwFDLCodeSize & 0x00FF0000) >> 16 ) << 8
//             | dwFDLCodeSize >> 24;
//         memcpy( (LPBYTE)(lpBMFileInfo->lpCode) /* + 4 */ , (LPBYTE)&dwSizeValueEndian, 4 );
// 		
//         memcpy( (LPBYTE)(lpBMFileInfo->lpCode) + ADD_DOWNLOAD_LENGTH , lpCode, dwFDLCodeSize );  
//         lpBMFileInfo->dwCodeSize = dwFDLCodeSize + ADD_DOWNLOAD_LENGTH; 
//         ::UnmapViewOfFile( lpCode );
//         CloseHandle( hFDLCode);
//         CloseHandle( hFDLCodeMapView );
//     }
//     else
//     {
//         if( lpBMFileInfo->bChangeCode )
//         {
//             lpBMFileInfo->lpCode = new BYTE[ dwFDLCodeSize ];
//             memcpy( lpBMFileInfo->lpCode, lpCode, dwFDLCodeSize);        
//             ::UnmapViewOfFile( lpCode );
//             CloseHandle( hFDLCode);
//             CloseHandle( hFDLCodeMapView );
//         }
//         else
//         {
//             lpBMFileInfo->lpCode = lpCode;
//             lpBMFileInfo->hFDLCode = hFDLCode;
//             lpBMFileInfo->hFDLCodeMapView = hFDLCodeMapView;
//         }
//     }
//     
//     
//     return TRUE;    
// }

void CBMAFImp::UnloadBMFileInfo( PBMFileInfo lpBMFileInfo )
{
    if( lpBMFileInfo == NULL )
        return;
    
    if( lpBMFileInfo->bLoadCodeFromFile )
    {
        if( lpBMFileInfo->bChangeCode )
        {
            if( lpBMFileInfo->lpCode != NULL )
            {
                delete lpBMFileInfo->lpCode;
            }
        }
        else
        {
            if( lpBMFileInfo->lpCode != NULL )
            {
                ::UnmapViewOfFile( lpBMFileInfo->lpCode  );
            }
            if( lpBMFileInfo->hFDLCode != NULL )
            {
                ::CloseHandle( lpBMFileInfo->hFDLCode );
            }
            if( lpBMFileInfo->hFDLCodeMapView != NULL )
            {
                ::CloseHandle( lpBMFileInfo->hFDLCodeMapView );
            }
        }
    }
}

void CBMAFImp::ClearBMFiles()
{
	UINT  nCount = m_arrBMFileInfo.size();
    for(UINT i = 0; i < nCount ; i++ )
    {
        UnloadBMFileInfo( m_arrBMFileInfo[i] );
		delete[] m_arrBMFileInfo[i];
		m_arrBMFileInfo[i] = NULL;
    }
    
    m_arrBMFileInfo.clear();
    m_nBMFileCount = 0;
}
BOOL CBMAFImp::HasLog( void )
{
	_TCHAR szConfigFile[MAX_PATH];
    
    GetModuleFilePath( AfxGetInstanceHandle(), szConfigFile );
    _tcscat( szConfigFile,  _T("\\BMAF_log.ini") );
	CFileFind fileFind;
	if(fileFind.FindFile(szConfigFile))
	{
		return GetPrivateProfileInt(_T("Setting"),_T("Log_Mode"),0,szConfigFile);
	}
	else
		return FALSE;
}

