// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include <initguid.h>
#include "DLoader.h"

#include "MainFrm.h"

#include "Calibration.h"
#include "Calibration_Struct.h"

#include "DLoaderView.h"

#include "channelitf.h"

#include "BMFile.h"

#include "MasterImgGen.h"


#include <dbt.h>
#include <algorithm>

#include "BinPack.h"
#include "BarcodeDlg.h"

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

#include "ICommChannel.h"

#include "./phasecheck/PhaseCheckBuild.h"

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

#define FLASH_ADDRESS    0x30380000
//@Liu kai 2004-1-8 CR6797
#define FLASH_SIZE       0x7e000

#define STANDARD_SERIAL  _T("Serial")

#define NV_LENGTH      0x10000
#define RECORDS_OFFSET 0x1C00

#define  WM_RCV_DATA    WM_APP + 401

#define NV_AFC_SIZE      2//2

// Serial ports section
static TCHAR g_sz_SP[]   = _T("Serial port");
static TCHAR g_sz_Manu[] = _T("Manufactory");
static TCHAR g_sz_BR[]   = _T("Baud rate");

// Download files section
static TCHAR g_sz_DF[]   = _T("Download Files");

// Flash flag section
static TCHAR g_sz_FLASH[]      = _T("Flash");
static TCHAR g_sz_FLASH_FLAG[] = _T("Flash flag");

// NV flag section
static TCHAR g_sz_NV_PART[] = _T("NV");
static TCHAR g_sz_NV_FLAG[] = _T("Backup calibration");
static TCHAR g_sz_NV_REPL[] = _T("Replace flag");

#define WM_WARN_MESSAGEBOX (WM_USER+1000)
#define WM_INIT_PACKET     (WM_USER+1001)

unsigned short flash_get_checksum( DWORD addr, LPBYTE lpCode, DWORD len );

#define FLASH_SPANSION  0x00207E01
#define FLASH_SAMSUNG   0x0000E0EC
#define FLASH_NONE      0xFFFFFFFF

#define OPR_SUCCESS     (0)
#define OPR_FAIL        (1)
/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_SETTINGS, OnSettings)
ON_COMMAND(ID_START, OnStart)
ON_COMMAND(ID_STOP, OnStop)
ON_UPDATE_COMMAND_UI(ID_START, OnUpdateStart)
ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
ON_WM_CLOSE()
ON_UPDATE_COMMAND_UI(ID_SETTINGS, OnUpdateSettings)
ON_WM_HELPINFO()
ON_COMMAND(ID_LOAD_PACKET, OnLoadPacket)
ON_UPDATE_COMMAND_UI(ID_LOAD_PACKET, OnUpdateLoadPacket)
//}}AFX_MSG_MAP
// Global help commands
//    ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder)
//    ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)
//    ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
//    ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder)
ON_MESSAGE(WM_WARN_MESSAGEBOX,OnWarnMessageBox)
ON_MESSAGE(WM_INIT_PACKET,OnInitalPacket)
ON_MESSAGE(WM_STOP_ONE_PORT,OnStopOnePort)
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
		ID_INDICATOR_CAPS,
		ID_INDICATOR_NUM,
		ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame():m_sheetSettings(IDS_DL_SETTINGS)
{
    m_bStarted = FALSE;
	m_lStartNVRef = 0;
    ZeroMemory( m_lpReceiveBuffer , MAX_RECEIVE_SIZE );
    m_dwReceiveSize = 0;
	
    m_bAutoStart = FALSE;
    m_nFileCount = 0;
	m_pBMAF  = g_theApp.m_pBMAFramework;
	
    m_pMasterImg = NULL;
	
	m_bPacketOpen = FALSE;
	m_strSpecConfig = _T("");
	m_strPacketPath = _T("");
	m_aPacReleaseDir.RemoveAll();
	
	m_mapBMObj.RemoveAll();
	m_pNVFileBuf = NULL;
	m_dwReceiveSize = 0;
	m_pReportFile = NULL;
	
	m_dwMaxNVLength = NV_LENGTH;

	m_strOprErrorConfigFile = _T("BMError.ini");
	
	InitializeCriticalSection( &m_csReportFile );
	
#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	InitializeCriticalSection( &m_cs );
#endif
}//lint !e1401

CMainFrame::~CMainFrame()
{
	m_pBMAF = NULL;
	if(m_pMasterImg)
    {
		delete m_pMasterImg;
		m_pMasterImg = NULL;
    }
	
	if(m_pNVFileBuf!=NULL)
	{
		delete [] m_pNVFileBuf;
		m_pNVFileBuf = NULL;
	}
	
	DeleteCriticalSection( &m_csReportFile );
	
	if(NULL != m_pReportFile)
	{
		fclose(m_pReportFile);
		m_pReportFile = NULL;
	}
	
	DWORD dwPort = 0;	
    _BMOBJ  *pStruct = NULL;
	POSITION pos = m_mapBMObj.GetStartPosition();
    while( pos )
    {
        m_mapBMObj.GetNextAssoc( pos, dwPort, pStruct );
		if(pStruct->pBuf)
		{
			delete [] pStruct->pBuf;
		}
    }
	m_mapBMObj.RemoveAll();
	
#ifdef _DOWNLOAD_FOR_PRODUCTION
	DeleteCriticalSection( &m_cs );
	
    pos = m_mapPortData.GetStartPosition();
    while( NULL != pos )
    {
        DWORD dwKey;
        //HANDLE hEvent;
		PORT_DATA* pPortData;
        m_mapPortData.GetNextAssoc( pos, dwKey, pPortData );
        CloseHandle( pPortData->hSNEvent );
		SAFE_DELETE(pPortData->lpPhaseCheck);
		SAFE_DELETE(pPortData);
    }
	m_mapPortData.RemoveAll();
#endif

	ClearExtImgMap(m_mapUDiskIMg);
	ClearExtImgMap(m_mapChipDsp);

}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}
	
	
	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}
	
    SetMenu(NULL);
	
    
    //@ Liu Kai 2004-3-25 CR8123
    // Read .ini file
#ifndef _SPUPGRADE
#ifndef _DOWNLOAD_FOR_PRODUCTION	
    if(!LoadSettings())
    {
        AfxMessageBox(IDS_LOAD_SETTINGS_FAIL,MB_ICONSTOP);
        return -1;
    }
#endif
#endif
	
	// TODO: Delete these three lines if you don't want the toolbar to
	//  be dockable
	//	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	//	EnableDocking(CBRS_ALIGN_ANY);
	//	DockControlBar(&m_wndToolBar);
	
	UINT uStyle = m_wndToolBar.GetButtonStyle(1);
	uStyle |=  BS_FLAT;
	m_wndToolBar.SetButtonStyle(1,uStyle);
	
	m_wndToolBar.SetBitmaps(IDB_BMP_TOOLBAR,IDB_BMP_TOOLBAR_DIS,IDB_BMP_TOOLBAR_HOT);	

	int nIndex =0;
	CRect rcStatic;
	CRect rcWnd;
	GetClientRect(rcWnd);
	int nRight;
	nRight= rcWnd.right;
	nIndex= m_wndToolBar.CommandToIndex(ID_SPD_VERSION);
    m_wndToolBar.SetButtonInfo(nIndex,ID_SPD_VERSION,TBBS_SEPARATOR,800);
	m_wndToolBar.GetItemRect(nIndex,&rcStatic);
    rcStatic.top+=2;
	rcStatic.bottom-=2;
	//	rcStatic.right -= 400;
	m_wndToolBar.m_stcWnd.Create(_T(""),WS_CHILD|WS_VISIBLE |SS_LEFTNOWORDWRAP,rcStatic,&m_wndToolBar,ID_SPD_VERSION);
	m_wndToolBar.m_stcWnd.SetText(_T(""));
    m_wndToolBar.m_stcWnd.ShowWindow(SW_SHOWNA);
    m_wndToolBar.GetToolBarCtrl().EnableButton(ID_SPD_VERSION,TRUE);
	
#ifdef _SPUPGRADE
	SetWindowText(_T("SPUpgrade")); 	
	PostMessage(WM_INIT_PACKET);
#elif defined _DOWNLOAD_FOR_PRODUCTION
    SetWindowText(_T("Download"));	
	PostMessage(WM_INIT_PACKET);
#else
	SetWindowText(_T("DLoaderR")); 
	PostMessage(WM_INIT_PACKET);
#endif

	if(g_theApp.m_bCMDPackage)
	{
		AfxGetApp()->m_nCmdShow = SW_HIDE;
	}
	
	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
    cs.style &= ~FWS_ADDTOTITLE;	
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers


void CMainFrame::OnSettings() 
{
    m_sheetSettings.DoModal();
}

void CMainFrame::OnStart()
{
	CString strErrMsg;
    if( FAILED( CoInitialize(NULL) ) )
    {
        strErrMsg.LoadString( IDS_ATL_INIT_FAIL );
        AfxMessageBox( strErrMsg );
        return;
    }    
    m_arrFile.RemoveAll();
	m_sheetSettings.GetDownloadFile(m_arrFile);
	m_nFileCount = m_arrFile.GetSize();

	SAFE_DELETE_ARRAY(m_pNVFileBuf);


	//////////////////////////////////////////////////////////////////////////
	//  check files
	if(!CheckDLFiles())
	{
		return;
	}	
	
	//////////////////////////////////////////////////////////////////////////
	//  initialize report success infomation
	if(!InitReportInfo())
	{
		return;
	}
	
	//////////////////////////////////////////////////////////////////////////	
	// init NV buffer
	if(!InitNVBuffer())
	{
		return;
	}

	//////////////////////////////////////////////////////////////////////////	
	// init UDiskIMG buffers
	if(!InitUDiskBufMap())
	{
		return;
	}
	
	//////////////////////////////////////////////////////////////////////////	
	// init DSP files buffers
	if(!InitChipDspBufmap())
	{
		return;
	}
	
    m_bAutoStart = TRUE;
	
	((CDLoaderView *)(this->GetActiveView()))->StartDLTimer();
		
    StartWork();
}

void CMainFrame::StartWork()
{
    // Search valible serial ports and open them
    HKEY  hOpenKey;
    const cLen = 255;
    DWORD dwValueLen;
    DWORD dwDataLen;
    _TCHAR szValueName[cLen];
    _TCHAR szData[cLen];
    DWORD dwType;
    DWORD dwRet;
    int i = 0;
    int nSelPort = m_sheetSettings.GetComPort();
    CString strErrMsg;

  
    if((dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
        _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
        NULL,
        KEY_QUERY_VALUE | KEY_READ,
        &hOpenKey)) != ERROR_SUCCESS)
    {
        strErrMsg.LoadString( IDS_OPEN_REG_FAIL );
        if(AfxMessageBox( strErrMsg ,MB_YESNO) == IDNO)
		{
			CoUninitialize();
		}
		else
		{
			m_bStarted = TRUE;
		}
        return;
    }

    std::vector<int> lstPort;
	
    while(1)
    {
        dwValueLen = cLen;
        dwDataLen = cLen;
        szValueName[0] = 0;
        szData[0] = 0;
        
        dwRet = ::RegEnumValue(hOpenKey,
            i++,
            szValueName,
            &dwValueLen,
            NULL,
            &dwType,
            (BYTE*)szData,
            &dwDataLen
            );
        
        if(dwRet != ERROR_SUCCESS )
            break;
        
        int port;
        int nRet = _stscanf( szData,_T("COM%d"),&port );
        
        if( nRet == 0 )
            continue;
        
        if( nSelPort != 0 && nSelPort != port )
            continue;

		lstPort.push_back(port); 
    }
	
    RegCloseKey(hOpenKey);
	
	
	if(lstPort.size() != 0)
	{
		std::sort(lstPort.begin(),lstPort.end());

		for(UINT i = 0; i< lstPort.size(); i++)
		{			
#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
			if(g_theApp.m_bManual)
			{
				((CDLoaderView*)GetActiveView())->AddProg( lstPort[i], TRUE ); 
				CreatePortData( lstPort[i] );
			}
			else
			{
				// The port enumed is regarded as UART
				if( !StartOnePortWork(lstPort[i],TRUE) )
				{
					OnStop();
					return;
				}
			}
#else // _DLOADERR
			// The port enumed is regarded as UART
			if( !StartOnePortWork(lstPort[i],TRUE) )
			{
				OnStop();
				return;
			}
#endif
		}
	}

    
    m_bStarted = TRUE;

}

BOOL CMainFrame::StartOnePortWork( DWORD dwPort, BOOL bUart )
{
    CString strErrMsg = _T("");
    BYTE btOpenArgument[ 8 ];
    *(DWORD *)&btOpenArgument[ 0 ] = dwPort;
    if( m_sheetSettings.GetCmdBootFlag() )
    {
        *(DWORD *)&btOpenArgument[ 4 ] = DEFAULT_BAUDRATE;    
    }
    else
    {
        *(DWORD *)&btOpenArgument[ 4 ] = m_sheetSettings.GetBaudRate();   
    }
	
    HRESULT hr = 0;        
    DWORD dwWaitTime = m_sheetSettings.GetWaitTimeForNextChip();

#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
	if(g_theApp.m_bManual)
	{// manual to control download start. so it will close the port, when download finished.
		dwWaitTime = 0;		
	}
#endif

	m_pBMAF->BMAF_SetProperty(BMAF_TIME_WAIT_FOR_NEXT_CHIP,dwWaitTime);
	
	
    CComPtr<IBMOprObserver> pObserver;
    hr = GetControllingUnknown()->QueryInterface( IID_IBMOprObserver,(LPVOID*)&pObserver );
    if( SUCCEEDED( hr ))
    {
		m_pBMAF->BMAF_SubscribeObserver( dwPort,pObserver, NULL );
    }     
	
	m_pBMAF->BMAF_SetProperty(BMAF_NAND_REPARTION_FLAG, m_sheetSettings.GetRepartitionFlag() );
	
	CString strNULL = _T("");	
	
	m_pBMAF->BMAF_SetProperty(BMAF_SPECIAL_CONFIG_FILE, (DWORD)(LPCTSTR)m_strSpecConfig );
	
    CString strNVFileName = _T("");
	if(m_sheetSettings.IsReadFlashInFDL2() || m_sheetSettings.IsHasLang())
	{
		CString strNVFileType;
		PFILE_INFO_T pNVFile = NULL;
		int nIdx = m_sheetSettings.GetFileInfo(_T("NV"),(LPDWORD)&pNVFile);
		if(nIdx != -1 && pNVFile != NULL)
		{
			strNVFileType = pNVFile->szType;
			m_pBMAF->BMAF_SetProperty(BMAF_SPEC_FILE_TYPE,(DWORD)(LPCTSTR)strNVFileType);
			
			strNVFileName = m_arrFile.GetAt(nIdx);
		}
		
	}
	else
	{
		m_pBMAF->BMAF_SetProperty(BMAF_SPEC_FILE_TYPE,(DWORD)(LPCTSTR)strNULL);
	}
	
	m_pBMAF->BMAF_SetProperty(BMAF_READ_FLASH_BEFORE_REPARTITION, (DWORD)m_sheetSettings.IsReadFlashInFDL2());
	
	
	LPCTSTR *ppFileList = new LPCTSTR[m_nFileCount];
	for(int i = 0; i<m_nFileCount; i++)
	{
		ppFileList[i] = (LPCTSTR)m_arrFile.GetAt(i);
		TRACE(_T("FILE[%d]:%s\n"),i,ppFileList[i]);
	}
	
	_BMOBJ     * pStruct = NULL;
	if( m_mapBMObj.Lookup(dwPort, pStruct) )
    {
		if(pStruct->pBuf)
		{
			delete [] pStruct->pBuf;
			pStruct->pBuf = NULL;
			pStruct->dwBufSize = 0;
		}

		pStruct->dwCookie = dwPort;
		pStruct->dwIsUart = bUart;
		
		memset(pStruct->szErrorMsg,0,sizeof(pStruct->szErrorMsg));
		memset(pStruct->szSN,0,sizeof(pStruct->szSN));
    }
	else
	{
		pStruct = new _BMOBJ;
		if( pStruct == NULL )
        {
            strErrMsg.LoadString( IDS_NEWOPR_FAIL );
            AfxMessageBox( strErrMsg );
            return FALSE;                        
        }

		pStruct->dwCookie = dwPort;
		pStruct->dwIsUart = bUart;

		m_mapBMObj.SetAt(dwPort,pStruct);
	}

    m_mapBMObj.Lookup(dwPort, pStruct);

	if(m_sheetSettings.IsReadFlashInFDL2() || m_sheetSettings.IsHasLang())
	{
		_ASSERTE(!strNVFileName.IsEmpty() && strNVFileName.CompareNoCase(FILE_OMIT) != 0);
		
		if(m_dwNvFileSize == 0)
		{
			AfxMessageBox( _T("NV file is empty!") );
			return FALSE;
		}
        pStruct->dwBufSize = m_dwNvFileSize;
		
		pStruct->pBuf = new BYTE[pStruct->dwBufSize];
		
		memcpy(pStruct->pBuf, m_pNVFileBuf,m_dwNvFileSize);
	}
	
	
    hr = m_pBMAF->BMAF_StartOneWork( m_sheetSettings.GetCurProduct(),
		ppFileList, 
		m_nFileCount,
		(DWORD)btOpenArgument, 
		TRUE, 
		dwPort, 
		FALSE, 
		(DWORD)(GetActiveView()->GetSafeHwnd()),
		L"UartManager.UartObj" );
	delete [] ppFileList;
	ppFileList = NULL;
	
    BOOL bReturn = TRUE;
	BOOL bFirst = TRUE;
	PBOOTMODEOBJ_T pBMO = NULL;
	m_pBMAF->BMAF_GetBootModeObjInfo(dwPort,(LPDWORD)&pBMO);
	bFirst = pBMO->bFirstStart;
	
    switch( hr )
    {
    case BM_E_CREATETHREAD_FAILED:
        strErrMsg.LoadString( IDS_CREATETHREAD_FAIL );
        bReturn =  FALSE;   
        break;
    case BM_E_FILEINFO_ERROR:
        strErrMsg.LoadString( IDS_FILEINFO_ERROR );
        bReturn =  FALSE;   
        break;
    case BM_E_OPR_NOTREG:
        strErrMsg.LoadString( IDS_BMOPR_NOTREG );
        bReturn =  FALSE;   
        break;
    case BM_E_FAILED:
        strErrMsg.LoadString( IDS_START_FAIL );
        bReturn =  FALSE;   
        break;
	case BMAF_E_INIT_BMFILES_FAIL:		
		strErrMsg = pStruct->szErrorMsg; // prepare file fail, mainly for making master image
		if(strErrMsg.IsEmpty())
		{
			strErrMsg.Format(_T("Init BMFiles failed!"));
		}
        bReturn =  FALSE;   
        break;
    default:
		//if(bFirst)
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
		if(!g_theApp.m_bManual)
		{
			((CDLoaderView*)GetActiveView())->AddProg( dwPort, SUCCEEDED(hr) ); 
		}
#else
		((CDLoaderView*)GetActiveView())->AddProg( dwPort, SUCCEEDED(hr) ); 
#endif
        break;        
    }
	
    if( FALSE == bReturn )
    {
		if(!strErrMsg.IsEmpty())
		{
			AfxMessageBox( strErrMsg );
		}
		m_pBMAF->BMAF_StopOneWork( dwPort);
		m_pBMAF->BMAF_UnsubscribeObserver( dwPort );
        return FALSE;        
    }     
    RecalcLayout(); 
    return TRUE;
}

BOOL CMainFrame::StopOnePortWork(DWORD dwPort,BOOL bRemoved /*= FALSE*/)
{
	UNREFERENCED_PARAMETER(bRemoved);
	HRESULT hr;
    PBOOTMODEOBJ_T pStruct = NULL;	
	hr = m_pBMAF->BMAF_GetBootModeObjInfo(dwPort,(LPDWORD)&pStruct);
	if( SUCCEEDED(hr) && pStruct != NULL )
	{
		if(!pStruct->bStop)
		{
#ifdef _DOWNLOAD_FOR_PRODUCTION
			DL_STAGE stage;
			((CDLoaderView*)GetActiveView())->GetStatus((int)dwPort, stage);
			if ( stage != DL_FINISH_STAGE )
#endif
				((CDLoaderView*)GetActiveView())->SetResult( dwPort,FALSE,NULL,0 );
		}
		else
		{
			// for release port
			pStruct->bStop = FALSE;
		}	

#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
		((CDLoaderView *)GetActiveView())->ClearPortInfo(dwPort);
		PORT_DATA *pPortData = NULL;
		if( m_mapPortData.Lookup(dwPort, pPortData) )
		{
			if(pPortData != NULL)
			{
				SetEvent(pPortData->hSNEvent);
				CloseHandle(pPortData->hSNEvent);
				SAFE_DELETE(pPortData->lpPhaseCheck);
				SAFE_DELETE(pPortData);
			}

			m_mapPortData.RemoveKey(dwPort);
		}		
#endif

		//m_pBMAF->BMAF_StopOneWork(dwPort);
		DWORD dwParam[2] = {0};
		dwParam[0] = (DWORD)this;
		dwParam[1] = dwPort;
		
		DWORD dwThreadID = 0;
		HANDLE hThread = CreateThread(NULL,
            0,
            (LPTHREAD_START_ROUTINE)GetThreadFunc,
            (LPVOID)dwParam,
            NULL,
            &dwThreadID);

		MSG msg;
		while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

        if( hThread == NULL)
        {
            m_pBMAF->BMAF_StopOneWork(dwPort);	
        }
		else
		{
			WaitForSingleObject( hThread, 5000);
			CloseHandle( hThread);
			hThread = NULL;
		}
					
	}
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
	if(!bRemoved && g_theApp.m_bManual)
	{
		((CDLoaderView *)GetActiveView())->AddProg(dwPort,TRUE);
		CreatePortData(dwPort);	
	}
#endif

	return TRUE;
}

void CMainFrame::OnStop()
{
    CWaitCursor wait;
	
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined (_SPUPGRADE)
	POSITION pos = m_mapPortData.GetStartPosition();
    DWORD dwCookie = 0;
    
    PORT_DATA* pPortData = NULL;
    while( pos )
    {
        m_mapPortData.GetNextAssoc( pos, dwCookie, pPortData );
		SetEvent(pPortData->hSNEvent);        
	}
#endif
    
    m_pBMAF->BMAF_StopAllWork();
	m_arrFile.RemoveAll();
	m_nFileCount = 0;
	
	
    ((CDLoaderView*)GetActiveView())->RemoveAll();
    m_bStarted = FALSE;
    m_bAutoStart = FALSE;
	m_lStartNVRef = 0;
    if( m_pMasterImg )
    {
        delete m_pMasterImg;
        m_pMasterImg = NULL;
    }
	
	if(NULL != m_pReportFile)
	{
		fclose(m_pReportFile);
		m_pReportFile = NULL;
	}

	((CDLoaderView *)(this->GetActiveView()))->StopDLTimer();
	
    //CoUninitialize(); 
}

void CMainFrame::OnUpdateStart(CCmdUI* pCmdUI) 
{
#if defined( _DOWNLOAD_FOR_PRODUCTION ) || defined(_SPUPGRADE)
	BOOL bOK = m_bPacketOpen &&!m_bStarted && m_sheetSettings.IsMainPageInit();
#else // _DLOADERR
    BOOL bOK = !m_bStarted && m_sheetSettings.IsMainPageInit();
#endif
	
    pCmdUI->Enable(bOK);
}

void CMainFrame::OnUpdateStop(CCmdUI* pCmdUI) 
{
#if defined(_SPUPGRADE)
	//not allowed to click stop button when dealing with NV
	pCmdUI->Enable( m_bStarted && m_lStartNVRef == 0 );
#elif defined _DOWNLOAD_FOR_PRODUCTION
	pCmdUI->Enable( m_bStarted && m_lStartNVRef == 0 );
#else
	pCmdUI->Enable(m_bStarted);	
#endif
}

void CMainFrame::OnClose() 
{
	if(m_bStarted)
    {
        CString str;
        str.LoadString(IDS_QUIT_TEST);
        AfxMessageBox(str);
    }
    else
    {
        ShowWindow(SW_HIDE);
        //SaveSettings();
		if(g_theApp.m_pBMAFramework != NULL)
			g_theApp.m_pBMAFramework->BMAF_Release();
        
			/*
			// Wait all download threads end
			while(m_pComStatus->GetRef() > 1)// for test
			{
			// Maybe the downloading thread will send
			// some message before it ends,so here we
			// check the message queue to retrieve and 
			// process the message
			MSG msg;
			while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
			{
			DispatchMessage( &msg );
			}
			
			  ::Sleep(1);
	}*/
//#if defined(_SPUPGRADE) || defined(_DOWNLOAD_FOR_PRODUCTION)
		CString strPath = _T("");
		CBinPack bp;
		int n = m_aPacReleaseDir.GetSize();
		for(int i = 0; i< n; i++)
		{
			strPath = m_aPacReleaseDir.GetAt(i);
			if(!strPath.IsEmpty())
			{				
				bp.RemoveReleaseDir(strPath);
			}
		}
		m_aPacReleaseDir.RemoveAll();
//#endif
        if(m_pNVFileBuf)
		{
			delete [] m_pNVFileBuf;
			m_pNVFileBuf = NULL;
		}
		m_pNVFileBuf = NULL;
		m_dwNvFileSize = 0;
        
		CFrameWnd::OnClose();
    }
}


void CMainFrame::OnUpdateSettings(CCmdUI* pCmdUI) 
{
	// Disable Settings button while downloading
#if defined(_SPUPGRADE) || defined(_DOWNLOAD_FOR_PRODUCTION)
	pCmdUI->Enable(m_bPacketOpen && !m_bStarted);
#else
    pCmdUI->Enable(!m_bStarted);
#endif	
}

//@ Liu Kai 2004-3-25 CR8123
BOOL CMainFrame::LoadSettings()
{
    _TCHAR szFilePath[_MAX_PATH]={0};
    if(!GetIniFilePath(szFilePath))
    {
        return FALSE;
    }
	_TCHAR szAppPath[_MAX_PATH]={0};
	GetModuleFilePath(g_theApp.m_hInstance,szAppPath);
	CFileFind finder;

#ifdef USE_FLASHINFO
	CString strFlashInfoFile;
	strFlashInfoFile.Format(_T("%s\\FlashInfo.fic"),szAppPath);
	if(!finder.FindFile(strFlashInfoFile))
		return FALSE;
	else
	{
		if(!m_FlashInfo.LoadFlashInfo(strFlashInfoFile))
			AfxMessageBox(_T("Load FlashInfo.fic failed"));		
	}
#endif //USE_FLASHINFO
	
	CString strBMFileType;
	strBMFileType.Format(_T("%s\\BMFileType.ini"),szAppPath);	
	if(finder.FindFile(strBMFileType))
	{
		m_dwMaxNVLength = GetPrivateProfileInt(_T("DownloadNV"),_T("MaxReadLength"),NV_LENGTH,strBMFileType);
	}
	

    m_strOprErrorConfigFile.Format(_T("%s\\BMError.ini"),szAppPath); 
	
    return m_sheetSettings.LoadSettings(szFilePath);    
}

void CMainFrame::SaveSettings()
{
    _TCHAR szFilePath[_MAX_PATH]={0};
    if(!GetIniFilePath(szFilePath))
    {
        return;
    }
	
    DWORD dwAttr = GetFileAttributes(szFilePath);
    if(-1 != dwAttr)
    {
        dwAttr &= ~FILE_ATTRIBUTE_READONLY;
        ::SetFileAttributes(szFilePath,dwAttr);
    }
	
    m_sheetSettings.SaveSettings(szFilePath);
}


BOOL CMainFrame::GetIniFilePath(LPTSTR pName)
{
    if(pName == NULL)
        return FALSE;
	
    DWORD dwRet = ::GetModuleFileName(AfxGetApp()->m_hInstance,pName,_MAX_PATH);
    if(dwRet == 0)
    {
        pName[0] = 0;
        return FALSE;
    }
	
    LPTSTR pResult = _tcsrchr(pName,_T('.'));
    if(pResult == NULL)
    {
        pName[0] = 0;
        return FALSE;
    }
	
    *pResult = 0;
    _tcscat(pName,_T(".ini"));
	
    return TRUE;
}

HRESULT  CMainFrame::ProcessData(   DWORD pChannel , LPBYTE lpData, int iDataLen  )
{
	
    if( iDataLen > MAX_RECEIVE_SIZE )
    {
        ((ICommChannel*)pChannel)->FreeMem( lpData );
        return E_FAIL;        
    }
	
    if( m_dwReceiveSize + iDataLen > MAX_RECEIVE_SIZE )
    {
        ZeroMemory( m_lpReceiveBuffer, MAX_RECEIVE_SIZE );
        m_dwReceiveSize = 0;   
    }
	
    memcpy( m_lpReceiveBuffer + m_dwReceiveSize, lpData, iDataLen );
    m_dwReceiveSize += iDataLen;
	
    ((ICommChannel*)pChannel)->FreeMem( lpData );
	
    LPBYTE lpStart = (LPBYTE)memchr(m_lpReceiveBuffer,FLAG_BYTE,m_dwReceiveSize);
    if( lpStart != 0 )
    {
        int nStart = lpStart - m_lpReceiveBuffer;
        m_dwReceiveSize -= nStart;
        memmove( m_lpReceiveBuffer,lpStart,m_dwReceiveSize );
        
        LPBYTE lpEnd = (LPBYTE)memchr(m_lpReceiveBuffer + 1,FLAG_BYTE,m_dwReceiveSize);
        if(lpEnd != NULL)
        {
            const int rcvLen = 10;
            const BYTE bufRcv[] = {0x7E,0x00,0x00,0x00,0x00,0x00,0x08,0xFE,0x01,0x7E};
            
            if( memcmp( bufRcv,m_lpReceiveBuffer,rcvLen) == 0 )
            {
                return S_OK;
            }
        }
        else
        {
            return E_FAIL;
        }
    }
	
    ZeroMemory( m_lpReceiveBuffer, MAX_RECEIVE_SIZE );
    m_dwReceiveSize = 0;
    return E_FAIL;
	
}

BEGIN_INTERFACE_MAP(CMainFrame, CFrameWnd)
INTERFACE_PART( CMainFrame, IID_IBMOprObserver, BMOprObserver)
END_INTERFACE_MAP()

STDMETHODIMP_(ULONG) CMainFrame::XBMOprObserver::AddRef()
{
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		return (ULONG)pThis->ExternalAddRef();
}

STDMETHODIMP_(ULONG) CMainFrame::XBMOprObserver::Release()
{
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		return (ULONG)pThis->ExternalRelease();
}

STDMETHODIMP CMainFrame::XBMOprObserver::QueryInterface( REFIID iid, LPVOID* ppvObj)
{
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnOperationStart( THIS_ DWORD dwOprCookie, 
														  const BSTR cbstrFileID,
                                                          const BSTR cbstrFileType, 
                                                          const BSTR cbstrOperationType,
                                                          DWORD pBMFileInterface )
{
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		UNUSED_ALWAYS( dwOprCookie );
	UNUSED_ALWAYS( cbstrFileID );
    UNUSED_ALWAYS( pBMFileInterface );
    
	//	CString strFileType(OLE2T( cbstrFileType));
	//	CString strOprType(OLE2T( cbstrOperationType));	
	
	CString strErrMsg = _T("");
	_BMOBJ * pbj = NULL;
	if( !pThis->m_mapBMObj.Lookup(dwOprCookie,pbj) ||  NULL == pbj )	
	{
		return E_FAIL;
	}
	
	if( _tcsicmp( OLE2T( cbstrFileType ), _T("NAND_FDL_OPT")) == 0
		&& _tcsicmp( OLE2T( cbstrOperationType ),_T("ReadFlash")) == 0 
		&& pThis->m_sheetSettings.IsReadFlashInFDL2())
	{
		int nIndex= 0;
		IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
		
		BOOTMODEOBJ_T *pStruct = NULL;
		HRESULT hr;
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		if(SUCCEEDED(hr))
		{
			nIndex = (int)(pStruct->dwFileIndex);
		}
		
		PFILE_INFO_T pNVFileInfo = NULL;
		if(pThis->m_sheetSettings.GetFileInfo(_T("NV"),(LPDWORD)&pNVFileInfo) == -1)
		{
			strErrMsg.Format( _T("Can not find NV!"));
			_tcscpy(pbj->szErrorMsg,strErrMsg);
			return E_FAIL;
		}
		
		if(pNVFileInfo != NULL)
		{
			pBMFile->SetCurCodeBase(pNVFileInfo->arrBlock[nIndex].dwBase);
			pBMFile->SetCurOprSize(pThis->m_dwMaxNVLength);
			DWORD dwNVPacketLength;
			pThis->m_pBMAF->BMAF_GetProperty(BMAF_SPEC_PACKET_LENGTH,&dwNVPacketLength);
			pBMFile->SetCurMaxLength(dwNVPacketLength);
			
		}
		
	}

//////////////////////////////////////////////////////////////////////////
#ifdef USE_FLASHINFO	
	if( _tcsicmp( OLE2T( cbstrFileType ), _T("FLASHINFO")) == 0
		&& _tcsicmp( OLE2T( cbstrOperationType ),_T("DownFlashSpec")) == 0
		&&pThis->m_sheetSettings.IsUseFlashSpec() )
	{
		
		IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
		
		BOOTMODEOBJ_T *pStruct = NULL;
		HRESULT hr;
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
		if(FAILED(hr))
		{
			return E_FAIL;
		}
		PFLASH_SPEC_T pFlashSpec = NULL;
		
		pFlashSpec = pThis->m_FlashInfo.GetFlashInfo(pStruct->dwFlashInfo[0],pStruct->dwFlashInfo[1],
			pStruct->dwFlashInfo[2]	);
		
		if( NULL == pFlashSpec)
		{
			strErrMsg.Format( _T("Can not find flash configure [FlashID:0x%X] [DeviceID:0x%X] [ExtendID:0x%X]!"),
				pStruct->dwFlashInfo[0],pStruct->dwFlashInfo[1],pStruct->dwFlashInfo[2]	);
			_tcscpy(pbj->szErrorMsg,strErrMsg);
			return E_FAIL;
		}		
		pStruct->dwFlashType = pThis->m_FlashInfo.ConvEdnDWORD(pFlashSpec->dwReserved[9]); // flash unique id 
		DWORD dwIndex;
		if(pThis->m_sheetSettings.GetFlashBaseIndex(pStruct->dwFlashType,dwIndex))
		{
			pStruct->dwFileIndex = dwIndex;
		}
		else
		{
			strErrMsg.Format(_T("Unkown flash unique id: 0x%X"),pStruct->dwFlashType);
			_tcscpy(pbj->szErrorMsg,strErrMsg);
			return E_FAIL;							
		}
		pFlashSpec->dwReserved[9] = 0;
		
		pBMFile->SetCurCode((LPVOID)pFlashSpec,sizeof(FLASH_SPEC_T)); 
		pThis->m_FlashInfo.RelaseMem( pFlashSpec );		
	}
#endif //USE_FLASHINFO
//////////////////////////////////////////////////////////////////////////

	
#ifdef _DOWNLOAD_FOR_PRODUCTION
	if( _tcsicmp( OLE2T( cbstrFileID ), _T("PhaseCheck")) == 0 && 
		_tcsicmp( OLE2T( cbstrFileType ), _T("CODE")) == 0 &&
		_tcsicmp( OLE2T( cbstrOperationType ),_T("Download")) == 0)
	{
		PORT_DATA* pPortData = NULL;
		BOOL bFound = pThis->m_mapPortData.Lookup(dwOprCookie, pPortData);
		if( bFound )
		{
			IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
			pBMFile->SetCurCode(pPortData->lpPhaseCheck, PRODUCTION_INFO_SIZE);
		}	
		else
		{
			TRACE(_T("Cannot find information about Port:%d"), dwOprCookie);
			_ASSERT(0);
		}
		
	}
#endif
    return S_OK;
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnOperationEnd( THIS_ DWORD dwOprCookie, 
														const BSTR cbstrFileID,
														const BSTR cbstrFileType, 
														const BSTR cbstrOperationType,
														DWORD dwResult,
														DWORD pBMFileInterface)
{
    UNUSED_ALWAYS( cbstrFileID );
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		USES_CONVERSION;
	
	HRESULT hr = NULL;
	PBOOTMODEOBJ_T pStruct = NULL;
	/*
    if( dwResult &&
	stricmp( OLE2T(cbstrOperationType),"Reset") == 0  )
    {
	return pThis->InitModule( dwOprCookie );
    }
	*/
	CString strErrMsg = _T("");
	_BMOBJ * pbj = NULL;
	if( !pThis->m_mapBMObj.Lookup(dwOprCookie,pbj) ||  NULL == pbj )	
	{
		return E_FAIL;
	}

//#ifdef _DEBUG
//	strErrMsg.Format( _T("Test %s failed"), OLE2T( cbstrFileType ) );
//	_tcscpy(pbj->szErrorMsg,strErrMsg);
//	return E_FAIL;
//#endif 
	if(OPR_SUCCESS != dwResult)
	{
		if( OPR_FAIL != dwResult)
		{
			pThis->GetOprErrorCodeDescription(dwResult,pbj->szErrorMsg,_MAX_PATH);
		}
		return E_FAIL;
	}

    if( ( _tcsicmp( OLE2T( cbstrFileType ), _T("FileStart")) == 0  ||
        _tcsicmp( OLE2T( cbstrFileType ), _T("FileEnd")) == 0 ) &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlash")) == 0 )
    {        
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
        if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer * pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL )
            {
                return E_FAIL;
            }
            LPBYTE lpDLCode =  new BYTE[dwReadSize];
            memcpy( lpDLCode, lpReadBuffer, dwReadSize );
            
            DWORD* lpBuffer = (DWORD*)( lpDLCode + RECORDS_OFFSET );
            int nCount = ( dwReadSize - RECORDS_OFFSET ) / sizeof(DWORD);
            for( int i = 0; i < nCount; i++ )
            {
                if( *( lpBuffer + i ) == 0xFFFFFFFF )
                {
                    break;
                }
            }
            
            if( _tcsicmp( OLE2T( cbstrFileType ), _T("FileStart")) == 0  )
            {
                if(i == nCount)
                {
                    // The buffer are full filled,so we erase the former 64 records
                    memcpy( lpBuffer, (BYTE*)lpBuffer + nCount / 2 * sizeof(DWORD) ,nCount / 2 * sizeof(DWORD));
                    memset( (BYTE*)lpBuffer + nCount / 2 * sizeof(DWORD),0xFF, nCount / 2 * sizeof(DWORD));
                    i = nCount / 2;
                }
                
                time_t ltime;
                time(&ltime);
                *(lpBuffer + i) = ltime;
                *(lpBuffer + i + 1) = 0;                
            }
            else
            {
                *( lpBuffer + i - 1 ) = 1; 
            }
            
            IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
            pBMFile->SetCurCode( lpDLCode, dwReadSize );
            delete [] lpDLCode;                  
        }        
        return S_OK ;
    }   
	
    if(  _tcsicmp( OLE2T( cbstrFileType), _T("EraseFlash2")) == 0 &&
        ( _tcsicmp( OLE2T(cbstrOperationType),_T("EraseFlash")) == 0  || 
        _tcsicmp( OLE2T(cbstrOperationType),_T("EraseFlash2")) == 0 ) )
    {
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
        if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer * pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD) )
            {
                return E_FAIL;
            }
            LPBYTE lpDLCode =  new BYTE[ dwReadSize ];
            DWORD dwDLSize = dwReadSize;
            memcpy( lpDLCode, lpReadBuffer, dwReadSize );
            /*
            if( dwReadSize & 0x1 == 1 )
            {
			dwDLSize = dwReadSize - 1;
			lpDLCode = new BYTE[ dwDLSize ];
			memcpy( lpDLCode, lpReadBuffer, dwDLSize);
            }
            else
            {
			dwDLSize = dwReadSize - 2;
			lpDLCode = new BYTE[ dwDLSize ];
			memcpy( lpDLCode, lpReadBuffer + 2, dwDLSize );
            }
            */
            IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
            DWORD dwStartAddr = pBMFile->GetCurCodeBase();
            dwStartAddr += 0x10000;
            unsigned short uichecksum = flash_get_checksum( dwStartAddr + 4, 
                lpDLCode + 4,  dwDLSize - 4 );
            *(unsigned short*)&lpDLCode[2] = uichecksum;
            pBMFile->SetCurCodeBase( dwStartAddr );
            pBMFile->SetCurCode( lpDLCode, dwDLSize );
            delete []lpDLCode;                  
        }        
        return S_OK;    
    }
    
    if( _tcsicmp( OLE2T( cbstrFileType), _T("CODE")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadChipType")) == 0 )
    {
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
        if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer* pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD) )
            {
                return E_FAIL;
            }
			
            DWORD dwSoruceValue, dwDestValue;            
            dwSoruceValue =  *(DWORD *)&lpReadBuffer[ 0 ];    
            dwDestValue   = 0;
            CONVERT_INT( dwSoruceValue, dwDestValue);  
        }
        return S_OK;
    }
	
    if( _tcsicmp( OLE2T( cbstrFileType), _T("READFLASHTYPE")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlashType")) == 0 )
    {
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
		if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer * pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD) )
            {
                return E_FAIL;
            }
            
            pStruct->dwFlashType = *(DWORD *)&lpReadBuffer[ 0 ]; 
			DWORD dwIndex;
			if(pThis->m_sheetSettings.GetFlashBaseIndex(pStruct->dwFlashType,dwIndex))
			{
				pStruct->dwFileIndex = dwIndex;
			}
			else
			{
				pStruct->dwFileIndex = 0;				
			}
        }
        return S_OK;
    }  

//////////////////////////////////////////////////////////////////////////
#ifdef USE_FLASHINFO
    if( _tcsicmp( OLE2T( cbstrFileType), _T("FLASHINFO")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlashInfo")) == 0 )
    {
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
		if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer *pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD)*3 )
            {
				strErrMsg.Format(_T("Read Flash Info failed."));
				_tcscpy(pbj->szErrorMsg,strErrMsg);
                return E_FAIL;
            }
            LPDWORD pDw = (LPDWORD)lpReadBuffer;
            pStruct->dwFlashInfo[0] = pThis->m_FlashInfo.ConvEdnDWORD(*pDw); 
			pStruct->dwFlashInfo[1] = pThis->m_FlashInfo.ConvEdnDWORD(*(pDw+1)); 
			pStruct->dwFlashInfo[2] = pThis->m_FlashInfo.ConvEdnDWORD(*(pDw+2));
        }
		
        return S_OK;
    }  
#endif //USE_FLASHINFO
//////////////////////////////////////////////////////////////////////////
	
	//read sn from flash
	if( _tcsicmp( OLE2T( cbstrFileType), _T("ReadSN")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlash")) == 0 )
    {
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
		if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer * pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }

			if(lpReadBuffer != NULL && dwReadSize >= PRODUCTION_INFO_SIZE)
			{
				CPhaseCheckBuild pcb;
				pcb.FindSnFrom8K(lpReadBuffer,dwReadSize,(BYTE*)pbj->szSN,X_SN_LEN);
			}

        }
        return S_OK;
    } 
	
	/************************************************************************/
	/*  backup NV                                                           */
	/************************************************************************/
    if( (_tcsicmp( OLE2T( cbstrFileID), _T("NV")) == 0 &&
		 pThis->m_sheetSettings.IsBackupNV() &&
		_tcsnicmp( OLE2T( cbstrFileType), _T("NV"), 2 ) == 0 &&
		_tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlash")) == 0 ) ||		  
		( pThis->m_sheetSettings.IsReadFlashInFDL2() &&
        _tcsicmp( OLE2T( cbstrFileType), _T("NAND_FDL_OPT")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlash")) == 0 ))
    {
		IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
		
		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
		if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            DWORD dwCodeSize = 0;
			LPVOID pDestCode = NULL;
            IBMOprBuffer * pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
			else
			{
				strErrMsg.Format(_T("Read Flash (NV) failed."));
				_tcscpy(pbj->szErrorMsg,strErrMsg);
				return E_FAIL;
			}
            if( lpReadBuffer == NULL )
            {
				strErrMsg.Format(_T("Read Flash (NV) failed."));
				_tcscpy(pbj->szErrorMsg,strErrMsg);
                return E_FAIL;
            }           
            
			if( _tcsnicmp( OLE2T( cbstrFileType), _T("NV"), 2 ) == 0 )
			{				
				const LPVOID pSrcCode = pBMFile->GetCurCode();
				dwCodeSize = pBMFile->GetCurCodeSize();
				pDestCode = pSrcCode;
			}
			else
			{
				dwCodeSize = pbj->dwBufSize;
				pDestCode = (LPVOID)(pbj->pBuf);
			}

			BOOL bBackupTDCali = FALSE;
			PNV_BACKUP_ITEM_T pNvBkpItem = NULL;
			int nCount = pThis->m_sheetSettings.GetNvBkpItemCount();
			BOOL bTdReplace = FALSE;
			BOOL bTdContinue = FALSE;
			BOOL bReplace = FALSE;
			BOOL bContinue = FALSE;
			for(int k=0;k<nCount;k++)
			{
				bReplace = FALSE;
				bContinue = FALSE;
				
				pNvBkpItem = pThis->m_sheetSettings.GetNvBkpItemInfo(k);
				
				int nNvBkpFlagCount = pNvBkpItem->dwFlagCount;
				if(nNvBkpFlagCount > MAX_NV_BACKUP_FALG_NUM)
				{
					nNvBkpFlagCount = MAX_NV_BACKUP_FALG_NUM;
				}
				for(int m=0;m<nNvBkpFlagCount;m++)
				{
					if(_tcscmp(pNvBkpItem->nbftArray[m].szFlagName,_T("Replace"))==0)
					{
						if(pNvBkpItem->nbftArray[m].dwCheck == 1)
							bReplace = TRUE;
					}
					else if(_tcscmp(pNvBkpItem->nbftArray[m].szFlagName,_T("Continue"))==0)
					{
						if(pNvBkpItem->nbftArray[m].dwCheck == 1)
							bContinue = TRUE;
					}
				}
				
				if(_tcscmp(pNvBkpItem->szItemName,_T("Calibration"))==0)
				{
					if(pNvBkpItem->wIsBackup == 1)
					{
						DWORD dwErrorRCID = PreserveCalibration( (LPBYTE)pDestCode, dwCodeSize, lpReadBuffer, dwReadSize, 
							bReplace, bContinue);
						if(  dwErrorRCID !=0  )
						{
							strErrMsg = GetErrorDesc( dwErrorRCID );
							strErrMsg.Format( _T("Preserve calibration fail [%s]."), strErrMsg );
							_tcscpy(pbj->szErrorMsg,strErrMsg);
							return E_FAIL;
						}						
					}
					continue;					
				}
				else if(_tcscmp(pNvBkpItem->szItemName,_T("TD_Calibration"))==0)
				{					
					if(pNvBkpItem->wIsBackup == 1)
					{
						bTdContinue = bContinue;
						bTdReplace = bReplace;
						bBackupTDCali = TRUE;
					}
				}
				else if(_tcscmp(pNvBkpItem->szItemName,_T("IMEI"))==0)
				{
					if(pNvBkpItem->wIsBackup == 1)
					{
						if ( !PreserveIMEI( (LPBYTE)pDestCode, dwCodeSize, lpReadBuffer, dwReadSize ) )
						{
							strErrMsg = _T("Preserve IMEI fail.");
							_tcscpy(pbj->szErrorMsg,strErrMsg);
							return E_FAIL;
						}
					}
					continue;					
				}
				else
				{
					if(pNvBkpItem->wIsBackup == 1 && pNvBkpItem->dwID != 0xFFFFFFFF)
					{
						if ( !PreserveNVItemEx( (WORD)(pNvBkpItem->dwID),(LPBYTE)pDestCode, dwCodeSize, 
							lpReadBuffer, dwReadSize, bReplace, bContinue) )
						{
							strErrMsg.Format(_T("Preserve %s fail."),pNvBkpItem->szItemName);
							_tcscpy(pbj->szErrorMsg,strErrMsg);
							return E_FAIL;
						}
					}
					continue;	
				}
			}
			/************************************************************************/
			/* backup multi-language item                                           */
			/************************************************************************/
			WORD wLangID = pThis->m_sheetSettings.GetLangNVItemID();
			if(pThis->m_sheetSettings.IsBackupLang() && wLangID != 0xFFFF)
			{
				if(!PreserveNVItemEx(wLangID,(LPBYTE)pDestCode, dwCodeSize,lpReadBuffer, dwReadSize))
				{
					strErrMsg.Format(_T("Preserve multi-language item fail."));
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}
			}

			/*----------------For TD BEGINE-------------------------------------------------------*/
			DWORD dwNvAfcSize = 0;
			BOOL bDoPreserveTDNVItem = TRUE;
			CString strProduct = pThis->m_sheetSettings.GetCurProduct();
			
			if( ( strProduct.CompareNoCase(_T("DualMode_TD")) == 0  ||
				strProduct.CompareNoCase( _T("Cali_TD") ) == 0 ) && bBackupTDCali )
			{	
				CString strApcFile = pThis->m_sheetSettings.GetDownloadFilePath(_T("APC"));
				CString strAgcFile = pThis->m_sheetSettings.GetDownloadFilePath(_T("AGC"));
				BYTE readBuffer[ 2048 ]={0};
				FILE* pFile = NULL;
				DWORD dwSize = 0;
				//判断APC文件中是否包含AFC
				if(!strApcFile.IsEmpty() && strApcFile.CompareNoCase(FILE_OMIT) !=0)
				{
					HANDLE hFile = CreateFile(strApcFile, 
						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( hFile == INVALID_HANDLE_VALUE)
					{   
						strErrMsg= _T( "Load APC file fail.");
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
					
					DWORD dwApcFileSize = GetFileSize( hFile, NULL);
					
					if(dwApcFileSize >= NV_AFC_SIZE + APC_SIZE )
						dwNvAfcSize = NV_AFC_SIZE;
					CloseHandle( hFile);
					
				}
				DWORD dwOffsize = 4 - dwNvAfcSize;
				if( !strApcFile.IsEmpty() && strApcFile.CompareNoCase(FILE_OMIT) !=0)
				{
					pFile = _tfopen( strApcFile, _T("rb"));
					if( pFile != NULL )
					{
						fseek( pFile, 0, SEEK_SET );
						fread( readBuffer, 1, dwNvAfcSize + APC_SIZE , pFile );
						dwSize = dwNvAfcSize + APC_SIZE;
						fclose( pFile );
					}
					else
					{
						strErrMsg= _T( "Load APC file fail.");
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
				}
				else
				{
					dwOffsize += dwNvAfcSize +  APC_SIZE; 
				}
				
				if( !strAgcFile.IsEmpty() && strAgcFile.CompareNoCase(FILE_OMIT) !=0 )
				{
					pFile = _tfopen( strAgcFile, _T("rb"));
					if( pFile != NULL )
					{
						fseek( pFile, 0, SEEK_SET );
						fread( readBuffer + dwSize, 1, AGC_SIZE, pFile );
						dwSize += AGC_SIZE;
						fclose( pFile );
					}
					else
					{
						strErrMsg= _T( "Load AGC file fail.");
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
				}			
				
				if( dwSize != 0 )
				{
					bDoPreserveTDNVItem = FALSE;
					if( !PreserveTDCalibration( (LPBYTE)pDestCode, dwCodeSize, readBuffer, dwSize, dwOffsize,dwNvAfcSize ) )
					{
						strErrMsg= _T( "Preserve TD Calibration fail.");
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
				}
			}
			if ( bDoPreserveTDNVItem && bBackupTDCali)
			{
//				if( !PreserveNVItem( 0x516, (LPBYTE)pDestCode, dwCodeSize, lpReadBuffer, dwReadSize ) )
//				{
//					pThis->m_strErrMsg= _T( "Preserve TD NV item [ID:0x516] fail.");
//					return E_FAIL;
//				}
				DWORD dwErrorRCID = PreserveTDCalibrationEx( (LPBYTE)pDestCode, dwCodeSize, lpReadBuffer, dwReadSize, 
					bTdReplace,bTdContinue);
				if(  dwErrorRCID !=0  )
				{
					strErrMsg = GetErrorDesc( dwErrorRCID );
					strErrMsg.Format( _T("Preserve TD calibration fail [%s]."), strErrMsg );
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}
			}
			/*----------------For TD END-------------------------------------------------------*/
			
			if( _tcsnicmp( OLE2T( cbstrFileType), _T("NV"), 2 ) == 0 )
			{
				if(pThis->m_sheetSettings.IsNvBaseChange())
				{
					PFILE_INFO_T pNvFileInfo = NULL;
					pThis->m_sheetSettings.GetFileInfo(OLE2T(cbstrFileID),(LPDWORD)&pNvFileInfo);
					int nPos = pThis->m_sheetSettings.GetNvNewBasePosition();
					if(nPos<0 || nPos>=MAX_BLOCK_NUM)
					{
						strErrMsg.Format(_T("The position index [%d] of the new Nv address is incorrect."),nPos);
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
					
					DWORD dwNewBase = pNvFileInfo->arrBlock[nPos].dwBase;
					pBMFile = (IBMFile*)pBMFileInterface;
					pBMFile->SetCurCodeBase(dwNewBase);
				}
				
				// backup to memory				
				if(pbj->pBuf == NULL || pbj->dwBufSize == 0)
				{
					pbj->pBuf = new BYTE[dwCodeSize];
					pbj->dwBufSize = dwCodeSize;
				}
				memcpy(pbj->pBuf,pDestCode,dwCodeSize);				
			}
			
			if (pThis->m_sheetSettings.IsNVSaveToLocal())
			{
				CString strLocalPath = pThis->m_sheetSettings.GetNVSavePath();
				
				if(strLocalPath.IsEmpty())
				{
					strErrMsg.Format(_T("NV save to local: the path is empty."));
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}//end if(strLocalPath.IsEmpty())			
				
				CString strFullPath;				

				BOOL bSNEmpty = FALSE;
				if(strlen(pbj->szSN)==0)
				{
					bSNEmpty = TRUE;
				}//end if(strlen(pbj->szSN)==0)
				HANDLE hFile = INVALID_HANDLE_VALUE;

				if(!bSNEmpty)
				{
					
#if defined(_UNICODE) || defined(UNICODE)
					_TCHAR szWSN[100]={0};
					MultiByteToWideChar(CP_ACP,0,pbj->szSN,strlen(pbj->szSN),szWSN,100);
					strFullPath.Format(_T("%s\\%s.bin"),strLocalPath,szWSN);
#else
					strFullPath.Format(_T("%s\\%s.bin"),strLocalPath,pbj->szSN);
#endif
					DWORD dwAtt = 0;
					CFileFind finder;
					if(finder.FindFile(strFullPath))
					{
						dwAtt	= ::GetFileAttributes(strFullPath);
						dwAtt &= ~FILE_ATTRIBUTE_READONLY;
						::SetFileAttributes(strFullPath,dwAtt);
					}//end if(finder.FindFile(strFullPath))
					finder.Close();				
					
					hFile = CreateFile(strFullPath,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
					
				}
				
				if(!bSNEmpty && hFile != INVALID_HANDLE_VALUE)						
				{
					DWORD dwWritten=0;
					WriteFile(hFile,pDestCode,dwCodeSize,&dwWritten,NULL);
				}//end if(!bSNEmpty && hFile != INVALID_HANDLE_VALUE)	
				else // maybe there is no SN in phone, so there maybe be invalidate char in SN buffer
				{    // use IMEI replace of SN as file name.
					DWORD dwIMEIOffset=0;
					DWORD dwIMEILen =0;						
					_TCHAR szWIMEI[100]={0};
					char szIMEI[100]={0};
					if (FindNVOffset(0x5,(LPBYTE)pDestCode,dwCodeSize,dwIMEIOffset,dwIMEILen))
					{		
						BYTE bIMEI[100] ={0};
						memcpy(bIMEI,((LPBYTE)pDestCode) + dwIMEIOffset,dwIMEILen);							
						pThis->BCDToWString(bIMEI,dwIMEILen,szWIMEI,100);
#if defined(_UNICODE) || defined(UNICODE)
						WideCharToMultiByte(CP_ACP,0,szWIMEI,100,szIMEI,100,NULL,NULL);
#else
						strcpy(szIMEI,szWIMEI);
#endif
						if(strlen(szIMEI) < X_SN_LEN)
						{
							strcpy(pbj->szSN,szIMEI);
						}
					}//end if (FindNVOffset(0x5,(LPBYTE)pDestCode,dwCodeSize,dwIMEIOffset,dwIMEILen))	
					
					CTime timeCur = CTime::GetCurrentTime();
					strFullPath.Format(_T("%s\\%s_%4d-%02d-%02d_%02d-%02d-%02d_nv.bin"),strLocalPath,szWIMEI,
						timeCur.GetYear(),
						timeCur.GetMonth(),
						timeCur.GetDay(),
						timeCur.GetHour(),
						timeCur.GetMinute(),
						timeCur.GetSecond());
					hFile = CreateFile(strFullPath,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
					if(hFile != INVALID_HANDLE_VALUE)						
					{
						DWORD dwWritten=0;
						WriteFile(hFile,pDestCode,dwCodeSize,&dwWritten,NULL);
						
					}
					else
					{
						strErrMsg.Format(_T("[save nv to local] Create file [%s] fail."),strFullPath);
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
				}//end if(!bSNEmpty && hFile != INVALID_HANDLE_VALUE)	
				 //end else				
				
				CloseHandle(hFile);				
			} // end if(!bSNEmpty)
			else if(pThis->m_pReportFile != NULL)
			{
				DWORD dwIMEIOffset=0;
				DWORD dwIMEILen =0;						
				_TCHAR szWIMEI[100]={0};
				char szIMEI[100]={0};
				if (FindNVOffset(0x5,(LPBYTE)pDestCode,dwCodeSize,dwIMEIOffset,dwIMEILen))
				{		
					BYTE bIMEI[100] ={0};
					memcpy(bIMEI,((LPBYTE)pDestCode) + dwIMEIOffset,dwIMEILen);							
					pThis->BCDToWString(bIMEI,dwIMEILen,szWIMEI,100);
#if defined(_UNICODE) || defined(UNICODE)
					WideCharToMultiByte(CP_ACP,0,szWIMEI,100,szIMEI,100,NULL,NULL);
#else
					strcpy(szIMEI,szWIMEI);
#endif
					if(strlen(szIMEI) < X_SN_LEN)
					{
						strcpy(pbj->szSN,szIMEI);
					}	
				}
			}// end else if(pThis->m_pReportFile != NULL)
        }
		else
		{	
			return E_FAIL;		
		}
    }
	
	/************************************************************************/
	/* read nv 3 times if nv readed from phone is not correct               */
	/* check it by the nv memory in _BMOBJ.pBuf,if they are same            */
	/* it is validate                                                       */
	/************************************************************************/	
	if( _tcsicmp(OLE2T(cbstrFileID),_T("NV_REPEAT")) == 0
		&& _tcsnicmp( OLE2T( cbstrFileType), _T("NV"), 2 ) == 0 &&
		_tcsicmp( OLE2T(cbstrOperationType),_T("ReadFlash")) == 0 )
	{
		BOOL bValidate = TRUE;
		if(pbj->pBuf == NULL || pbj->dwBufSize == 0)
		{
			return E_FAIL;
		}

		hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);		
		if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            //DWORD dwCodeSize = 0;
            IBMOprBuffer *pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
			else
			{
				return E_FAIL;
			}

            if( lpReadBuffer == NULL )
            {
                return E_FAIL;
            }       
            
			// omit the first 2 crc bytes
			for(int i=sizeof(WORD); i< (int)pbj->dwBufSize ; i++)
			{
				if(pbj->pBuf[i] != lpReadBuffer[i])
				{
					bValidate = FALSE;
				}
			}

			IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
			pBMFile->SetCurCode((const LPVOID)(pbj->pBuf),pbj->dwBufSize);
			
			if(pThis->m_sheetSettings.IsNvBaseChange())
			{
				PFILE_INFO_T pNvFileInfo = NULL;
				pThis->m_sheetSettings.GetFileInfo(OLE2T(cbstrFileID),(LPDWORD)&pNvFileInfo);
				int nPos = pThis->m_sheetSettings.GetNvNewBasePosition();
				if(nPos<0 || nPos>=MAX_BLOCK_NUM)
				{
					strErrMsg.Format(_T("The position index [%d] of the new Nv address is incorrect."),nPos);
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}
				
				DWORD dwNewBase = pNvFileInfo->arrBlock[nPos].dwBase;
				pBMFile->SetCurCodeBase(dwNewBase);
			}

// #ifdef _DEBUG
//			static int ii= 0;
//			if(ii==0)
//			{
//				ii++;
// 				return E_FAIL;
//			}
// #endif

			if(bValidate)
			{
				return S_OK;
			}			
		}		
		return E_FAIL;
	}

	if( _tcsicmp( OLE2T( cbstrFileType), _T("UDISK_IMG")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadSectorSize")) == 0 )
    {
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
        if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer *pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD) )
            {
                return E_FAIL;
            }
			
            DWORD dwSoruceValue, dwSectorSize;            
            dwSoruceValue =  *(DWORD *)&lpReadBuffer[ 0 ];    
            dwSectorSize   = 0;
            CONVERT_INT( dwSoruceValue, dwSectorSize);  
	
			EXT_IMG_INFO_PTR pDiskImg = NULL;
			if(pThis->m_mapUDiskIMg.Lookup(dwSectorSize,pDiskImg))
			{
				IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
				if(!pBMFile->SetCurCode(pDiskImg->pBuf,pDiskImg->dwSize))
				{
					strErrMsg.Format(_T("Set udisk_img buffer to bootmodeplatform failed.[SetctorSize:%d]"),dwSectorSize);
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}
			}
			else
			{
				strErrMsg.Format(_T("Can not find udisk_img matching the sector size [%d]."),dwSectorSize);
				_tcscpy(pbj->szErrorMsg,strErrMsg);
				return E_FAIL;
			}
        }
        return S_OK;
    }


	if( _tcsicmp( OLE2T( cbstrFileType), _T("CHIP_DSP")) == 0 &&
        _tcsicmp( OLE2T(cbstrOperationType),_T("ReadChipType")) == 0 )
    {
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
		
        if( SUCCEEDED(hr) )
        {
            LPBYTE lpReadBuffer = NULL; 
            DWORD dwReadSize = 0;
            IBMOprBuffer *pBuffer;
            hr = pStruct->pSnapin->QueryInterface( IID_IBMOprBuffer, (LPVOID*)&pBuffer);
            if( SUCCEEDED(hr) )
            {
                lpReadBuffer = pBuffer->GetReadBuffer();
                dwReadSize = pBuffer->GetReadBufferSize();
            }
            if( lpReadBuffer == NULL || dwReadSize < sizeof( DWORD) )
            {
                return E_FAIL;
            }
			
            DWORD dwSoruceValue=0;
			DWORD dwChipID =0;            
            dwSoruceValue =  *(DWORD *)&lpReadBuffer[ 0 ];       
            CONVERT_INT( dwSoruceValue, dwChipID);  
	
			EXT_IMG_INFO_PTR pChipDsp = NULL;
			if(pThis->m_mapChipDsp.Lookup(dwChipID,pChipDsp))
			{
				IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
				if(!pBMFile->SetCurCode(pChipDsp->pBuf,pChipDsp->dwSize))
				{
					strErrMsg.Format(_T("Set dsp buffer to bootmodeplatform failed.[ChipID:0x%08X]."),dwChipID);
					_tcscpy(pbj->szErrorMsg,strErrMsg);
					return E_FAIL;
				}
			}
			else
			{
				strErrMsg.Format(_T("Can not find DSP file matching the chip ID[0x%08X]."),dwChipID);
				_tcscpy(pbj->szErrorMsg,strErrMsg);
				return E_FAIL;
			}
        }
        return S_OK;
    }
	
	
    return S_OK;
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnFileOprStart( THIS_ DWORD dwOprCookie,
														const BSTR cbstrFileID,
														const BSTR cbstrFileType, 
														DWORD pBMFileInterface )
{
    UNUSED_ALWAYS( cbstrFileType );
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		USES_CONVERSION;
	
    if( _tcsicmp( OLE2T( cbstrFileType), _T("NV")) == 0 )
    {
        InterlockedIncrement( &(pThis->m_lStartNVRef) );
    }
	
    ::PostMessage( ((CDLoaderView*)pThis->GetActiveView())->GetSafeHwnd(), 
		BM_FILE_BEGIN, dwOprCookie, 0 );
	
	HRESULT hr = NULL;
	PBOOTMODEOBJ_T pStruct = NULL;
	PFILE_INFO_T pFileInfo = NULL;
	IBMFile* pBMFile = (IBMFile*)pBMFileInterface;

	CString strErrMsg = _T("");
	_BMOBJ * pbj = NULL;
	if( !pThis->m_mapBMObj.Lookup(dwOprCookie,pbj) ||  NULL == pbj )	
	{
		return E_FAIL;
	}
	
	//	CString strFileID = OLE2T(cbstrFileID);
	//	CString strFileType = OLE2T(cbstrFileType);
	
	//    if( pThis->m_sheetSettings.GetCurProduct().Compare(_T("SP7370-DUAL")) == 0)
	//    {
	//        IBMFile* pBMFile = (IBMFile*)pBMFileInterface;
	//        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
	//        if( SUCCEEDED(hr) )
	//        {
	//			pThis->m_sheetSettings.GetFileInfo(OLE2T(cbstrFileID),(LPDWORD)&pFileInfo);
	//            if( pStruct->dwFlashType == FLASH_SAMSUNG )
	//            {
	//                pBMFile->SetCurCodeBase( pFileInfo->arrBlock[1].dwBase );
	//                if( _tcsicmp( OLE2T( cbstrFileType ),_T("EraseFlash") ) == 0 )
	//                {
	//                    pBMFile->SetCurOprSize( pFileInfo->arrBlock[1].dwSize );
	//                }
	//            }
	//        }        
	//     }
	
    if( pThis->m_sheetSettings.IsUseFlashType() || pThis->m_sheetSettings.IsUseFlashSpec())
    {
        
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
        if( SUCCEEDED(hr) )
        {
			pThis->m_sheetSettings.GetFileInfo(OLE2T(cbstrFileID),(LPDWORD)&pFileInfo);
			
			if(pStruct->dwFileIndex != 0)
			{
				pBMFile->SetCurCodeBase( pFileInfo->arrBlock[pStruct->dwFileIndex].dwBase );
				if( _tcsicmp( OLE2T( cbstrFileType ),_T("EraseFlash") ) == 0 )
				{
					pBMFile->SetCurOprSize( pFileInfo->arrBlock[pStruct->dwFileIndex].dwSize );
				}
			}  
        }        
    }
	
	if( _tcsicmp(OLE2T(cbstrFileID),_T("NV")) == 0 &&
		((pThis->m_sheetSettings.IsReadFlashInFDL2() && _tcsicmp(OLE2T(cbstrFileType),_T("CODE")) == 0) 
		|| pThis->m_sheetSettings.IsHasLang()))
	{
		if(pbj->pBuf == NULL || pbj->dwBufSize == 0)
		{
			return E_FAIL;
		}
		pBMFile->SetCurCode((const LPVOID)(pbj->pBuf),pbj->dwBufSize);		
		
		if(pThis->m_sheetSettings.IsNvBaseChange())
		{
			PFILE_INFO_T pNvFileInfo = NULL;
			pThis->m_sheetSettings.GetFileInfo(OLE2T(cbstrFileID),(LPDWORD)&pNvFileInfo);
			int nPos = pThis->m_sheetSettings.GetNvNewBasePosition();
			if(nPos<0 || nPos>=MAX_BLOCK_NUM)
			{
				strErrMsg.Format(_T("The position index [%d] of the new Nv address is incorrect."),nPos);
				_tcscpy(pbj->szErrorMsg,strErrMsg);
				return E_FAIL;
			}
			
			DWORD dwNewBase = pNvFileInfo->arrBlock[nPos].dwBase;
			//pBMFile = (IBMFile*)pBMFileInterface;
			pBMFile->SetCurCodeBase(dwNewBase);
		}
	}
	
	
    return S_OK;
														}
														
STDMETHODIMP CMainFrame::XBMOprObserver::OnFileOprEnd(    THIS_ DWORD dwOprCookie,
													  const BSTR cbstrFileID,
													  const BSTR cbstrFileType, 
													  DWORD dwResult )
{
    UNUSED_ALWAYS( dwOprCookie );
	UNUSED_ALWAYS( cbstrFileID );
    UNUSED_ALWAYS( cbstrFileType );
    UNUSED_ALWAYS( dwResult );
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		USES_CONVERSION;
    if( _tcsicmp( OLE2T( cbstrFileType), _T("NV")) == 0 )
    {
        InterlockedDecrement( &( pThis->m_lStartNVRef ) );
    }
    return S_OK;
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnEnd(  THIS_ DWORD dwOprCookie, 
											   DWORD dwResult )
{
    UNUSED_ALWAYS( dwOprCookie );
    UNUSED_ALWAYS( dwResult );
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)

	_BMOBJ * pbj = NULL;
	if( !pThis->m_mapBMObj.Lookup(dwOprCookie,pbj) ||  NULL == pbj )	
	{
		return E_FAIL;
	}

	BOOL bSucceed = TRUE;

	LPARAM lParam = NULL;
    if( dwResult != OPR_SUCCESS )
    {
		bSucceed = FALSE;
        lParam = (LPARAM)(LPCTSTR)pbj->szErrorMsg;
    }

    ::PostMessage( ((CDLoaderView*)pThis->GetActiveView())->GetSafeHwnd(), 
		BM_END, dwOprCookie, lParam );


	pThis->DoReport(dwOprCookie,bSucceed);    
	
    HRESULT hr;
    PBOOTMODEOBJ_T pStruct = NULL;	
	hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
	//If the port is "USB" regarded (may be not), or not wait for next chip
	//need stop the port to close the channel, prevent for "Blue screen"
	if(pThis->m_sheetSettings.GetWaitTimeForNextChip() == 0 ) 
	{
		pStruct->bStop = TRUE;	
	}

	if( (g_theApp.m_bClosePortFlag && pbj->dwIsUart != 1) || g_theApp.m_bManual )
	{
		pStruct->bStop = TRUE;	
		::PostMessage( pThis->GetSafeHwnd(), WM_STOP_ONE_PORT, dwOprCookie, 0 );
	}
	    
	/*    
    if(  (dwResult & 0x1) != 0  && ( dwResult & FACTORY_MODE ) == 0 )
    {
	::PostMessage( pThis->GetSafeHwnd(), WM_COMMAND, ID_STOP, 0 );
    }
	*/

	if(g_theApp.m_bScriptCtrl)
	{
		::PostMessage( pThis->GetSafeHwnd(), WM_COMMAND, ID_STOP, 0 );
		::PostMessage( pThis->GetSafeHwnd(), WM_CLOSE, 0, 0 );
	}


    return S_OK;
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnStart(  THIS_ DWORD dwOprCookie, 
												 DWORD dwResult )
{
    UNUSED_ALWAYS( dwOprCookie );
    UNUSED_ALWAYS( dwResult );
    METHOD_PROLOGUE(CMainFrame, BMOprObserver)
		
	HRESULT hr = NULL;
	PBOOTMODEOBJ_T pStruct = NULL;

#ifdef _DOWNLOAD_FOR_PRODUCTION
	if(!g_theApp.m_bManual)
	{
		if (OPR_SUCCESS != dwResult)
		{
			return S_OK;
		}
		
		PORT_DATA *pPortData = NULL;
		HANDLE hEvent = NULL;
		BOOL bFound = pThis->m_mapPortData.Lookup(dwOprCookie, pPortData);
		if( !bFound )
		{
			// There is no event associate with the port
			pPortData = pThis->CreatePortData( dwOprCookie );		
		}	
		hEvent = pPortData->hSNEvent;
		
		ResetEvent( hEvent );
		::PostMessage( pThis->GetActiveView()->GetSafeHwnd(), WM_REQUIRE_SN, dwOprCookie, (LPARAM)pPortData);
		WaitForSingleObject(hEvent, INFINITE);
	}
#endif
	
	if(pThis->m_sheetSettings.IsUseFlashType() || pThis->m_sheetSettings.IsUseFlashSpec())
	{
        hr = pThis->m_pBMAF->BMAF_GetBootModeObjInfo(dwOprCookie,(LPDWORD)&pStruct);
        if( SUCCEEDED(hr) )
        {
            pStruct->dwFlashType = FLASH_NONE;
			pStruct->dwFileIndex = 0;
        }   
	}
    
    if( OPR_SUCCESS == dwResult && pThis->m_sheetSettings.GetCmdBootFlag() )
    {
        ::PostMessage( ((CDLoaderView*)pThis->GetActiveView())->GetSafeHwnd(), 
            BM_BEGIN, dwOprCookie, 0);
        hr = pThis->InitModule( dwOprCookie );
        if( FAILED( hr ) )
		{
			return hr;
		}
    }
	
    return S_OK;
}

STDMETHODIMP CMainFrame::XBMOprObserver::OnFilePrepare(THIS_ DWORD dwOprCookie,
													   const BSTR bstrProduct,
													   const BSTR bstrFileName,
													   DWORD lpFileInfo,
													   /*[out]*/ DWORD      pBMFileInfoArr,
													   /*[out]*/ LPDWORD    lpBMFileInfoCount,
													   /*[out]*/ LPDWORD    lpdwFlag)
{
	UNUSED_ALWAYS(bstrProduct);
	UNUSED_ALWAYS(dwOprCookie);
	METHOD_PROLOGUE(CMainFrame, BMOprObserver)
	USES_CONVERSION;

	CString strErrMsg = _T("");
	_BMOBJ * pbj = NULL;
	if( !pThis->m_mapBMObj.Lookup(dwOprCookie,pbj) ||  NULL == pbj )	
	{
		return E_FAIL;
	}
	
	*lpdwFlag = 0; //不做处理
	PBMFileInfo pBMFileInfo = (PBMFileInfo)pBMFileInfoArr;
	if(lpFileInfo == NULL)
	{
		CUIntArray agFlashOprFiles;
		int nFlashOprCount = pThis->m_sheetSettings.GetFlashOprFileInfo(agFlashOprFiles);
		if(nFlashOprCount > MAX_RET_FILE_NUM)
		{
			return E_FAIL;
		}
		for(int i= 0; i< nFlashOprCount; i++)
		{
			PFILE_INFO_T pFileInfo = (PFILE_INFO_T)agFlashOprFiles[i];
			PBMFileInfo pBMFileInfoCur = pBMFileInfo+i;

			CString strFilePath = pFileInfo->szFilePath;
			int nFind = strFilePath.ReverseFind(_T('\\'));
			CString strPrefix;
			strPrefix.Format(_T("COM%d_"),dwOprCookie);
			if(nFind != -1)
			{
				strFilePath.Insert(nFind+1,strPrefix);
			}
			else
			{
				strFilePath.Insert(0,strPrefix);
			}			

			_tcscpy(pBMFileInfoCur->szFileID,pFileInfo->szID);
			_tcscpy(pBMFileInfoCur->szFileType, pFileInfo->szType);
			_tcscpy(pBMFileInfoCur->szFileName,strFilePath);
			pBMFileInfoCur->dwBase = pFileInfo->arrBlock[0].dwBase;
			pBMFileInfoCur->dwOprSize = pFileInfo->arrBlock[0].dwSize;
			pBMFileInfoCur->bChangeCode = FALSE;
			pBMFileInfoCur->bLoadCodeFromFile = FALSE;

			CString strID = pFileInfo->szID;
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
			
		}

		*lpdwFlag = 1;
		*lpBMFileInfoCount= nFlashOprCount;
		
		return S_OK;
	}


	PFILE_INFO_T pFileInfo = (PFILE_INFO_T)lpFileInfo;
	
	CString strID = pFileInfo->szID;
	CString strFileType = pFileInfo->szType;
    // if product Nand flash
	if( pThis->m_sheetSettings.IsNandFlash())
	{
		// if product is DualMode, that is say it has GSM and TD file elements
		if( pThis->m_sheetSettings.IsProdDualMode())
		{
			// if GSM and TD file are not omitted
			if(pThis->m_sheetSettings.IsDualMode())
			{
				if(strID.CompareNoCase(_T("GSM"))==0)
				{
					*lpdwFlag = 1;
					*lpBMFileInfoCount =0;   
				}
				
				if(_tcsicmp(pFileInfo->szID,_T("TD"))==0)
				{
					IMAGE_PARAM imageparam[2];
					int nImag =0;
					PFILE_INFO_T pFIT = NULL;
					CString strPath;
					int nIndex = pThis->m_sheetSettings.GetFileInfo(_T("GSM"),(LPDWORD)&pFIT);
					if(nIndex != -1)
					{
						strPath = pThis->m_arrFile.GetAt(nIndex);
					}
					if(!strPath.IsEmpty())
					{
						memset(imageparam,0,sizeof(IMAGE_PARAM));
						_tcscpy(imageparam[0].szPath,strPath);
						strcpy(imageparam[0].szName,"GSM");
						nImag++;
					}
					
					memset(imageparam+nImag,0,sizeof(IMAGE_PARAM));
					_tcscpy(imageparam[nImag].szPath,OLE2T(bstrFileName));
					strcpy(imageparam[nImag].szName,"TD");
					nImag++;
					
					_tcscpy(pBMFileInfo->szFileID,_T("PS")); //change GSM and TD to PS
					_tcscpy(pBMFileInfo->szFileType,_T("CODE")); 
					pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
					pBMFileInfo->bLoadCodeFromFile = FALSE;
					CMasterImgGen mig;
					pBMFileInfo->lpCode = mig.MakeMasterImage( &pBMFileInfo->dwCodeSize,nImag,imageparam,pThis->m_sheetSettings.GetFlashPageType() );
					if(pBMFileInfo->lpCode == NULL)
					{						
						strErrMsg.Format(_T("Make master image faile! [%s]"),pFileInfo->szID);
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
					
					*lpdwFlag = 1;
					*lpBMFileInfoCount =1;	
					CString strIDTemp = _T("PS");
					((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strIDTemp);
				}
			}
			else // one or both of GSM and TD file are omitted
			{
				if( strID.CompareNoCase(_T("GSM"))==0 || strID.CompareNoCase(_T("TD")) == 0 )
				{
					_tcscpy(pBMFileInfo->szFileID,pFileInfo->szID);
					_tcscpy(pBMFileInfo->szFileType,pFileInfo->szType);
					_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
					pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
					IMAGE_PARAM imageparam;
					pBMFileInfo->bLoadCodeFromFile = FALSE;
					memset( &imageparam,0,sizeof( IMAGE_PARAM ) );
					_tcscpy( imageparam.szPath,OLE2T(bstrFileName) );
					CMasterImgGen mig;
					pBMFileInfo->lpCode = mig.MakeMasterImage( &pBMFileInfo->dwCodeSize,1,&imageparam,pThis->m_sheetSettings.GetFlashPageType() );
					if(pBMFileInfo->lpCode == NULL)
					{
						strErrMsg.Format(_T("Make master image faile! [%s]"),pFileInfo->szID);
						_tcscpy(pbj->szErrorMsg,strErrMsg);
						return E_FAIL;
					}
					pThis->m_pMasterImg = pBMFileInfo->lpCode;
					
					//					_tcscpy(pBMFileInfo->szFileType, _T("CODE"));
					
					*lpdwFlag = 1;
					*lpBMFileInfoCount =1;	
					strID = pFileInfo->szID;
					((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
				}	
			}
		}
//		else  // product is not dualmode but is nand flash and has bootloader file element
//		{
//			if( strID.CompareNoCase(_T("KernelImg"))==0 || strID.CompareNoCase(_T("PS")) == 0 )
//			{
//				_tcscpy(pBMFileInfo->szFileID,pFileInfo->szID);
//				_tcscpy(pBMFileInfo->szFileType,pFileInfo->szType);
//				_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
//				pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
//				IMAGE_PARAM imageparam;
//				pBMFileInfo->bLoadCodeFromFile = FALSE;
//				memset( &imageparam,0,sizeof( IMAGE_PARAM ) );
//				_tcscpy( imageparam.szPath,OLE2T(bstrFileName) );
//				CMasterImgGen mig;
//				pBMFileInfo->lpCode = mig.MakeMasterImage( &pBMFileInfo->dwCodeSize,1,&imageparam,pThis->m_sheetSettings.GetFlashType() );
//				pThis->m_pMasterImg = pBMFileInfo->lpCode;
//
//				*lpdwFlag = 1;
//				*lpBMFileInfoCount =1;	
//				strID = pFileInfo->szID;
//				((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
//			}
// 		}
	}
	
	if( strFileType.CompareNoCase(_T("MasterImage"))==0 && !(pThis->m_sheetSettings.IsProdDualMode()))
	{
		_tcscpy(pBMFileInfo->szFileID,pFileInfo->szID);
        _tcscpy(pBMFileInfo->szFileType, _T("CODE"));
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
		IMAGE_PARAM imageparam;
		pBMFileInfo->bLoadCodeFromFile = FALSE;
		memset( &imageparam,0,sizeof( IMAGE_PARAM ) );
		_tcscpy( imageparam.szPath,OLE2T(bstrFileName) );
		CMasterImgGen mig;
		pBMFileInfo->lpCode = mig.MakeMasterImage( &pBMFileInfo->dwCodeSize,1,&imageparam,pThis->m_sheetSettings.GetFlashPageType() );
		
		if(pBMFileInfo->lpCode == NULL)
		{
			strErrMsg.Format(_T("Make master image faile! [%s]"),pFileInfo->szID);
			_tcscpy(pbj->szErrorMsg,strErrMsg);
			return E_FAIL;
		}
		pThis->m_pMasterImg = pBMFileInfo->lpCode;
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =1;	
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}	
	
    if( strID.CompareNoCase(_T("NV"))==0 )
	{
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,_T("NV"));

		// need to calculate the CRC16 and add to the head of NV
		// so the bChangeCode must be TRUE;
		pBMFileInfo->bChangeCode = TRUE;

		if(pThis->m_sheetSettings.IsReadFlashInFDL2())
		{
			//pBMFileInfo->bChangeCode = FALSE;
			_tcscpy(pBMFileInfo->szFileType, _T("CODE"));
		}
		else
		{
			//pBMFileInfo->bChangeCode = pThis->m_sheetSettings.IsBackupNV();
			if(pThis->m_sheetSettings.IsBackupNV()) // backup NV 4
				_tcscpy(pBMFileInfo->szFileType, pFileInfo->szType); // type is "NV" or "NV_NAND"
			else
				_tcscpy(pBMFileInfo->szFileType, _T("CODE"));
		}		
		pBMFileInfo->bLoadCodeFromFile = TRUE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
		pBMFileInfo->dwOprSize = pThis->m_dwMaxNVLength;		
		
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);

		int nInfoCount = 1;
		
		if(pThis->m_sheetSettings.IsNVOrgDownload())
		{
			int nPos = pThis->m_sheetSettings.GetNVOrgBasePosition();
			if(nPos<=0 || nPos >= 5)
			{
				strErrMsg.Format(_T("NV orignal base position [%d] is not correct,must be [1-4]!\nPlease check the production configure file!"),nPos);
				_tcscpy(pbj->szErrorMsg,strErrMsg);
				return E_FAIL;
			}
			PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
			_tcscpy(pBMFileInfo2->szFileName,OLE2T(bstrFileName));
			pBMFileInfo2->bLoadCodeFromFile = TRUE;
			pBMFileInfo2->bChangeCode = FALSE;
			_tcscpy(pBMFileInfo2->szFileType, _T("CODE")); 
			_tcscpy(pBMFileInfo2->szFileID,_T("NVOriginal"));
			pBMFileInfo2->dwBase = pFileInfo->arrBlock[nPos].dwBase;
			CString strDes = _T("NVOriginal");
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);
			nInfoCount++;
		}

		*lpdwFlag = 1;
		*lpBMFileInfoCount =nInfoCount;
	}

	if( (strID.CompareNoCase(_T("APC"))==0 || strID.CompareNoCase(_T("AGC"))==0)
		&& pFileInfo->arrBlock[0].dwBase == 0xFFFFFFFF)
	{
		*lpdwFlag = 1;
		*lpBMFileInfoCount =0;   
	}
	
	if(strID.CompareNoCase(_T("FDL")) == 0 && !pThis->m_sheetSettings.IsNandFlash())
	{
		
		// For FDL
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,pFileInfo->szID);
		pBMFileInfo->bChangeCode = FALSE;
		pBMFileInfo->bLoadCodeFromFile = TRUE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;	
		_tcscpy(pBMFileInfo->szFileType, pFileInfo->szType); 
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
		
		int nInfoCount = 1;
		
		if( pThis->m_sheetSettings.IsUseFlashType())
		{
			// add ReadFlashType function
			PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
			pBMFileInfo2->bLoadCodeFromFile = FALSE;
			_tcscpy(pBMFileInfo2->szFileType, _T("READFLASHTYPE")); 
			_tcscpy(pBMFileInfo2->szFileID,_T("ReadFlashType"));
			CString strDes = _T("ReadFlashType");
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);
			nInfoCount++;
			
		}
//////////////////////////////////////////////////////////////////////////
#ifdef USE_FLASHINFO
		if(pThis->m_sheetSettings.IsUseFlashSpec())
		{
			// add ReadFlashInfo function
			PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
			pBMFileInfo2->bChangeCode = TRUE;
			pBMFileInfo2->bLoadCodeFromFile = FALSE;
			_tcscpy(pBMFileInfo2->szFileType, _T("FLASHINFO")); 
			_tcscpy(pBMFileInfo2->szFileID,_T("FLASHINFO"));
			CString strDes = _T("FlashInfo");
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);
			nInfoCount++;
		}
#endif // USE_FLASHINFO
//////////////////////////////////////////////////////////////////////////
		if(pThis->m_sheetSettings.IsNVSaveToLocal())
		{
			PFILE_INFO_T pPhaseCheckFileInfo = NULL;
			if(pThis->m_sheetSettings.GetFileInfo(_T("PhaseCheck"),(LPDWORD)&pPhaseCheckFileInfo) != -1
				&& pPhaseCheckFileInfo != NULL)
			{
				// add Read SN function for saving NV to local as the name of NV file
				PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
				pBMFileInfo2->bLoadCodeFromFile = FALSE;
				_tcscpy(pBMFileInfo2->szFileType, _T("ReadSN")); 
				_tcscpy(pBMFileInfo2->szFileID,_T("ReadSN"));
				CString strDes = _T("ReadSN");
				((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);				
				
				pBMFileInfo2->dwBase = pPhaseCheckFileInfo->arrBlock[0].dwBase;
				pBMFileInfo2->dwOprSize = PRODUCTION_INFO_SIZE;
				
				nInfoCount++;
			}			
		}		
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =nInfoCount;	
	}	
	
	
	if(strID.CompareNoCase(_T("Fdl2")) == 0 && pThis->m_sheetSettings.IsNandFlash())
	{		
		// For Fdl2
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,pFileInfo->szID);
		pBMFileInfo->bChangeCode = FALSE;
		pBMFileInfo->bLoadCodeFromFile = TRUE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
		if(!pThis->m_sheetSettings.IsReadFlashInFDL2())
		{
			_tcscpy(pBMFileInfo->szFileType, pFileInfo->szType); 
		}
		else
		{
			_tcscpy(pBMFileInfo->szFileType, _T("NAND_FDL_OPT")); 
		}

		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);

		int nInfoCount = 1;

		if(pThis->m_sheetSettings.IsUseFlashType())
		{
			// add ReadFlashType function
			PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
			pBMFileInfo2->bLoadCodeFromFile = FALSE;
			_tcscpy(pBMFileInfo2->szFileType, _T("READFLASHTYPE"));
			_tcscpy(pBMFileInfo2->szFileID,_T("READFLASHTYPE"));
			CString strDes = _T("ReadFlashType");
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);
					
			nInfoCount++;	
		}

		if(pThis->m_sheetSettings.IsUseFlashSpec())
		{
			// add ReadFlashType function
			PBMFileInfo pBMFileInfo2 = pBMFileInfo + nInfoCount;
			pBMFileInfo2->bChangeCode = TRUE;
			pBMFileInfo2->bLoadCodeFromFile = FALSE;
			_tcscpy(pBMFileInfo2->szFileType, _T("FLASHINFO")); 
			_tcscpy(pBMFileInfo2->szFileID,_T("FLASHINFO"));
			CString strDes = _T("FlashInfo");
			((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strDes);			
		
			nInfoCount++;
		}

		*lpdwFlag = 1;
		*lpBMFileInfoCount =nInfoCount;	
		
	}	
	
#ifndef _DOWNLOAD_FOR_PRODUCTION	
	if( strID.CompareNoCase(_T("PhaseCheck"))==0 )
	{
		*lpdwFlag = 1;
		*lpBMFileInfoCount =0;	
	}
#else
	if( strID.CompareNoCase(_T("PhaseCheck"))==0 )
	{
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,_T("PhaseCheck"));
		
		pBMFileInfo->bChangeCode = FALSE;	
		_tcscpy(pBMFileInfo->szFileType, pFileInfo->szType); 

		
		pBMFileInfo->bLoadCodeFromFile = FALSE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
		pBMFileInfo->dwCodeSize = PRODUCTION_INFO_SIZE;	
		pBMFileInfo->lpCode = NULL;
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =1;
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}
#endif	
	
	if( strFileType.CompareNoCase(_T("UDISK_IMG"))==0 )
	{
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,strID);
		_tcscpy(pBMFileInfo->szFileType,strFileType);	
		pBMFileInfo->bChangeCode = TRUE;		
		pBMFileInfo->bLoadCodeFromFile = TRUE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;		
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =1;
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}

	if( strID.CompareNoCase(_T("DSPCode")) == 0 )
	{
		_tcscpy(pBMFileInfo->szFileName,OLE2T(bstrFileName));
		_tcscpy(pBMFileInfo->szFileID,strID);
		_tcscpy(pBMFileInfo->szFileType,strFileType);	
		pBMFileInfo->bChangeCode = FALSE;		
		pBMFileInfo->bLoadCodeFromFile = TRUE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;	
		
		if(pThis->m_sheetSettings.IsEnableChipDspMap())
		{
			_tcscpy(pBMFileInfo->szFileType,_T("CHIP_DSP"));
			pBMFileInfo->bChangeCode = TRUE;
		}
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =1;
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}

	if( strFileType.CompareNoCase(_T("ReadFlashAndSave"))==0 )
	{
		CString strFilePath = OLE2T(bstrFileName);
		int nFind = strFilePath.ReverseFind(_T('\\'));
		CString strPrefix;
		strPrefix.Format(_T("COM%d_"),dwOprCookie);
		if(nFind != -1)
		{
			strFilePath.Insert(nFind+1,strPrefix);
		}
		else
		{
			strFilePath.Insert(0,strPrefix);
		}
		
		_tcscpy(pBMFileInfo->szFileName,strFilePath);
		_tcscpy(pBMFileInfo->szFileID,strID);
		_tcscpy(pBMFileInfo->szFileType,strFileType);	
		pBMFileInfo->bChangeCode = FALSE;		
		pBMFileInfo->bLoadCodeFromFile = FALSE;
		pBMFileInfo->dwBase = pFileInfo->arrBlock[0].dwBase;
		pBMFileInfo->dwOprSize = pFileInfo->arrBlock[0].dwSize;
		
		*lpdwFlag = 1;
		*lpBMFileInfoCount =1;
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}

    // use for GUI display
	if(*lpdwFlag == 0 )
	{
		strID = pFileInfo->szID;
		((CDLoaderView *)(pThis->GetActiveView()))->AddStepDescription(strID);
	}
	pFileInfo = NULL;
	pBMFileInfo = NULL;
	
	return S_OK;
}

HRESULT CMainFrame::InitModule( DWORD dwOprCookie )
{
	
    ICommChannel* pChannel;
    HRESULT hr =m_pBMAF->BMAF_GetCommunicateChannelPtr(dwOprCookie,(LPVOID*)&pChannel );
    if( SUCCEEDED(hr) )
    {
        DWORD dwOldMsgID = 0;
        BOOL  bOldThread = FALSE;
        LPVOID pOldReceiver = NULL;
        pChannel->GetReceiver( dwOldMsgID, bOldThread, pOldReceiver );
        
        DWORD dwRecvThreadID = 0;
        DWORD aryArgument[ 2 ];
        aryArgument[ 0 ] = ( DWORD )this;
        aryArgument[ 1 ] = ( DWORD )pChannel;
        
        HANDLE hRecvThread = CreateThread(NULL,
            0,
            (LPTHREAD_START_ROUTINE)GetRcvDataThread,
            aryArgument,
            NULL,
            &dwRecvThreadID);
        if( hRecvThread == NULL)
        {
            return E_FAIL;		
        }
        
        pChannel->SetReceiver( WM_RCV_DATA ,TRUE, (LPVOID)dwRecvThreadID );
        
        ZeroMemory( m_lpReceiveBuffer, MAX_RECEIVE_SIZE );
		
        DWORD dwResult = WaitForSingleObject( hRecvThread, m_sheetSettings.GetWaitTimeForBootMode());
		
        pChannel->SetReceiver( dwOldMsgID ,bOldThread, pOldReceiver );
		
        if(  dwResult != WAIT_OBJECT_0 )
        {
            ::PostThreadMessage ( dwRecvThreadID, WM_QUIT, 0, 0);                
            WaitForSingleObject( hRecvThread, 1000 );                
            CloseHandle( hRecvThread);
            hRecvThread = NULL;
            return E_FAIL;
        }
        else
        {
            CloseHandle( hRecvThread);
            hRecvThread = NULL;                
        }
        
        const int sndLen = 10;
        const BYTE bufSnd[] = {0x7E,0x00,0x00,0x00,0x00,0x00,0x08,0xFE,0x82,0x7E};
        LONG  lWriteLen = pChannel->Write( (LPBYTE)bufSnd,sndLen );
        if( lWriteLen != sndLen )
        {    
            return E_FAIL;
        }
        Sleep( 1000 );
        int  nBaudrate = m_sheetSettings.GetBaudRate();
        pChannel->SetProperty( 0, CH_PROP_BAUD, (LPCVOID)&nBaudrate );
        return S_OK;
    } 
	
    return E_FAIL;
}

DWORD WINAPI CMainFrame::GetRcvDataThread( LPVOID lpParam )
{
    DWORD* pArgument = ( DWORD*)lpParam;
    DWORD arg1 = pArgument[ 0 ];
    
    CMainFrame * pThis = (CMainFrame*)arg1;
    DWORD pChannel =  pArgument[ 1 ];
    return pThis->RcvDataThreadProc( pChannel );
}

DWORD CMainFrame::RcvDataThreadProc(  DWORD pChannel  )
{
    MSG msg;
	
    // Set up the message queue
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
    
    // Wait for the UART data
    while ( GetMessage(&msg, NULL, 0, 0) )
    {
        switch ( msg.message )
        {
        case WM_RCV_DATA:
            {
                HRESULT hr = ProcessData( pChannel,( LPBYTE )msg.wParam , (int)msg.lParam );
                if( SUCCEEDED( hr ) )
                {
                    return 0;
                }
            }
            break;
        default:
            break;
        }
    }
	
    return 0;
}


unsigned short flash_get_checksum( DWORD addr, LPBYTE lpCode, DWORD len )
{
    unsigned short  check_sum = (unsigned short)(0xC50F + (unsigned short)addr);
    
    unsigned short uiSourceValue, uiDestValue;        
    for( UINT i = 0; i < len; i += sizeof(unsigned short) )
    {
        uiSourceValue =  *(unsigned short*)&lpCode[ i ];
        uiDestValue   = 0;
        CONVERT_SHORT( uiSourceValue, uiDestValue);
        check_sum = (unsigned short)(check_sum + uiDestValue);
    }
    uiSourceValue = check_sum;
    uiDestValue = 0;
    CONVERT_SHORT( uiSourceValue, uiDestValue );
    check_sum = uiDestValue;
    
    return check_sum;
}

LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class
	if( m_bAutoStart && (message == WM_DEVICECHANGE) )
    {
        PDEV_BROADCAST_HDR pdbh = (PDEV_BROADCAST_HDR)lParam;
		
        switch(wParam)
        {
        case DBT_DEVICEARRIVAL:
            if( pdbh != NULL && pdbh->dbch_devicetype == DBT_DEVTYP_PORT )
            {
                PDEV_BROADCAST_PORT pdbp = (PDEV_BROADCAST_PORT)lParam;
                _ASSERTE( _tcsstr(pdbp->dbcp_name, _T("COM")) != NULL );
				
				// skip COM
                int nPort = (int)_ttol( pdbp->dbcp_name + 3 ); //lint !e416
                _ASSERTE( nPort > 0 && nPort < 256 );
				
                Sleep(200);
				
                _ASSERTE( m_nFileCount > 0 && m_nFileCount < MAX_FILE_COUNT );
				
#ifndef _DOWNLOAD_FOR_PRODUCTION
                DL_STAGE stage;
                if( ((CDLoaderView*)GetActiveView())->GetStatus( nPort,stage ) )
                {
                    if( DL_FINISH_STAGE != stage && DL_NONE_STAGE != stage)
                    {
                        // Last download process is not finished.
                        break;
                    }
                }
#endif
				// The port plugged is regarded as USB
#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
				if(g_theApp.m_bManual)
				{
					((CDLoaderView*)GetActiveView())->AddProg( nPort, TRUE ); 
					CreatePortData( nPort );
				}
				else
				{
					StartOnePortWork(nPort,FALSE);	
				}
#else
                StartOnePortWork(nPort,FALSE);
#endif
            }
            break;
        case DBT_DEVICEREMOVECOMPLETE:
            if( pdbh != NULL && pdbh->dbch_devicetype == DBT_DEVTYP_PORT )
            {
				PDEV_BROADCAST_PORT pdbp = (PDEV_BROADCAST_PORT)lParam;
                _ASSERTE( _tcsstr(pdbp->dbcp_name, _T("COM")) != NULL );
				
                int nPort = (int)_ttol( pdbp->dbcp_name + 3 );//lint !e416
                _ASSERTE( nPort > 0 && nPort < 256 );
				
#ifndef _DOWNLOAD_FOR_PRODUCTION
				DL_STAGE _stage;
                if( ((CDLoaderView*)GetActiveView())->GetStatus( nPort,_stage ) )
                {
                    if( DL_NONE_STAGE == _stage)
                    {
                        // Last download process is not finished.
                        break;
                    }
                }
#endif
				StopOnePortWork((DWORD)nPort,TRUE);
				// CDLoaderView displays [Removed].
				((CDLoaderView*)GetActiveView())->SetResult( nPort,0,NULL,2);

            }
            break;
        default:
            break;
        }
    }
	
	return CFrameWnd::WindowProc(message, wParam, lParam);
}

/* 为了防止线程调用回调函数时使用AfxMessageBox发生阻塞
* 该函数主要在回调函数中使用PostMessage调用
* lpParam为对话框显示的文本字符串指针
*/
void CMainFrame::OnWarnMessageBox(WPARAM wParam,LPARAM lpParam)
{
	UNUSED_ALWAYS(wParam);
	ASSERT(lpParam != NULL);
	AfxMessageBox((LPCTSTR)lpParam);
}

BOOL CMainFrame::OnHelpInfo(HELPINFO* pHelpInfo) 
{
	UNUSED_ALWAYS(pHelpInfo);
	// TODO: Add your message handler code here and/or call default
	return TRUE;
	//return CFrameWnd::OnHelpInfo(pHelpInfo);
}

void CMainFrame::OnLoadPacket() 
{
	// TODO: Add your command handler code here	
	static _TCHAR BASED_CODE szFilter[] = _T("Packet Files (*.pac)|*.pac|All Files(*.*)|*.*||");
    CString strFile = _T("");
    CFileDialog dlg(TRUE, _T(".pac"), strFile,OFN_NOCHANGEDIR |OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, szFilter, NULL);
	
	if(dlg.DoModal() == IDCANCEL)
		return; 
	
	m_bPacketOpen = FALSE;
	
	m_strPacketPath = dlg.GetPathName();
	
	if(!m_sheetSettings.LoadPacket(m_strPacketPath))
	{
		AfxMessageBox(IDS_ERR_LOAD_PACKET_FAIL);
		return;	
	}

	m_bPacketOpen = TRUE;
	
	if(!LoadSettings())
    {
		m_bPacketOpen = FALSE;
        AfxMessageBox(IDS_LOAD_SETTINGS_FAIL,MB_ICONSTOP);
        return;
    }
	
	
	
#ifdef _DOWNLOAD_FOR_PRODUCTION
	m_sheetSettings.m_pageCalibration.m_lstBackup.m_bBackNV = FALSE;
	m_sheetSettings.m_pageMultiLang.m_bBackupLang = FALSE;
#endif	
	
	_TCHAR szFilePath[_MAX_PATH]={0};
    if(GetIniFilePath(szFilePath))
    {
		DWORD dwAttr = GetFileAttributes(szFilePath);
		if(-1 != dwAttr)
		{
			dwAttr &= ~FILE_ATTRIBUTE_READONLY;
			::SetFileAttributes(szFilePath,dwAttr);
		}
		WritePrivateProfileString(_T("Download_Packet"),_T("packet"),m_strPacketPath,szFilePath);		
	}
}

void CMainFrame::OnUpdateLoadPacket(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(!m_bPacketOpen || !m_bStarted);
}
CString CMainFrame::GetSpecConfigFile()
{
	return m_strSpecConfig;
}
void CMainFrame::SetPrdVersion(LPCTSTR lpszSpdVer)
{
	if(lpszSpdVer!= NULL)
	{
		m_wndToolBar.m_stcWnd.SetText(lpszSpdVer);
		m_wndToolBar.m_stcWnd.Invalidate();
	}
}


DWORD CMainFrame::BCDToWString(LPBYTE pBcd,DWORD dwSize,LPTSTR szStr,DWORD dwStrLen)
{
	if(dwStrLen < dwSize * 2 )
		return 0;
	
	_TCHAR szValue[ 4 ] = { 0 };
	
	for(UINT i=0;i<dwSize;i++)
	{
		_stprintf(szValue, _T("%02x"), *pBcd);
		if(i==0)
		{
			szStr[i]=szValue[0];
		}
		else
		{
			szStr[2*i-1]=szValue[1];
			szStr[2*i]=szValue[0];
		}
		
		pBcd++;
	}
	
	
	
	return dwSize*2-1;
}


void CMainFrame::OnInitalPacket(WPARAM wParam,LPARAM lpParam)
{
	UNUSED_ALWAYS(wParam);
	UNUSED_ALWAYS(lpParam);
	
	_TCHAR szIniFilePath[_MAX_PATH]={0};
	
	if(!GetIniFilePath(szIniFilePath))
	{
		return;
	}

	BOOL bPacketMode = GetPrivateProfileInt(_T("GUI"),_T("PacketMode"),0,szIniFilePath);

#if defined(_SPUPGRADE) || defined(_DOWNLOAD_FOR_PRODUCTION)
	bPacketMode = TRUE;
#endif
	if(!bPacketMode)
	{
// 		if(!LoadSettings())
// 		{
// 			m_bPacketOpen = FALSE;
// 			AfxMessageBox(IDS_ERR_CONIG_NOT_MATCH,MB_ICONSTOP);
// 			return;
// 		}
		return;
	}
	
	
	_TCHAR szPacPath[_MAX_PATH]={0};
	DWORD dwRet =  GetPrivateProfileString(_T("Download_Packet"),_T("packet"),_T(""),szPacPath,_MAX_PATH,szIniFilePath);
	if(dwRet == 0 )
		return;
	
	
	if(_tcslen(szPacPath) == 0)
		return;
	
	
	CFileFind finder;
	if(!finder.FindFile(szPacPath))
		return;	
	
	m_bPacketOpen = FALSE;
	
	m_strPacketPath = szPacPath;
	
	if(!m_sheetSettings.LoadPacket(m_strPacketPath))
	{
		AfxMessageBox(IDS_ERR_LOAD_PACKET_FAIL);
		return;	
	}

	m_bPacketOpen = TRUE;	
	
	if(!LoadSettings())
    {
		m_bPacketOpen = FALSE;
        AfxMessageBox(IDS_LOAD_SETTINGS_FAIL,MB_ICONSTOP);
        return;
    }
	
#ifdef _DOWNLOAD_FOR_PRODUCTION
	m_sheetSettings.m_pageCalibration.m_lstBackup.m_bBackNV = FALSE;
	m_sheetSettings.m_pageMultiLang.m_bBackupLang  = FALSE;
#endif
	
	
	
}

void CMainFrame::DoReport(DWORD dwOprCookie,BOOL bSuccess /*= TRUE*/)
{
	if(NULL == m_pReportFile && !g_theApp.m_bScriptCtrl)
		return;
	
	EnterCriticalSection( &m_csReportFile);
	// do success report
	_BMOBJ * pbj = NULL;
	char szSN[30] = "unknown";
	if(m_mapBMObj.Lookup(dwOprCookie,pbj) && pbj != NULL )
	{
		 strcpy(szSN,pbj->szSN);		 
	}
	if(m_pReportFile != NULL && bSuccess)
	{
		char szReport[MAX_PATH] = {0};
		CTime timeCur = CTime::GetCurrentTime();
		sprintf(szReport,"%4d-%02d-%02d %02d:%02d:%02d\t[COM%d] [SN/IMEI:%s] download success.\r\n",
			timeCur.GetYear(),
			timeCur.GetMonth(),
			timeCur.GetDay(),
			timeCur.GetHour(),
			timeCur.GetMinute(),
			timeCur.GetSecond(),
			dwOprCookie,
			szSN);
		fwrite(szReport,strlen(szReport),1,m_pReportFile);
		fflush(m_pReportFile);
	}
	//[[ for auto download
	if(g_theApp.m_bScriptCtrl)
	{
		CString strResultPath = g_theApp.m_strResultPath;
		if(g_theApp.m_bResultPathWithPort)
		{
			CString strCom;
			strCom.Format(_T("_com%d.txt"),dwOprCookie);
			strResultPath.Replace(_T(".txt"),strCom);
		}
		FILE *pFile = _tfopen(strResultPath,_T("wt"));
		
		CString strResult = _T("success");
		if(!bSuccess)
		{
			if(pbj != NULL && _tcslen(pbj->szErrorMsg)!=0 )
			{
				strResult = pbj->szErrorMsg;		
			}
			else
			{
				strResult = _T("unknown errors occur in downloading");
			}
		}

		_ftprintf(pFile,strResult);
		fclose(pFile);
	}
	//]]


	LeaveCriticalSection( &m_csReportFile);
}



#if defined(_DOWNLOAD_FOR_PRODUCTION) || defined(_SPUPGRADE)
PORT_DATA* CMainFrame::CreatePortData( DWORD dwPort )
{
    HANDLE hEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
	
    EnterCriticalSection( &m_cs );
	PORT_DATA * pPortDate = new PORT_DATA;
	pPortDate->dwPort = dwPort;
	pPortDate->hSNEvent = hEvent;
	pPortDate->lpPhaseCheck = NULL;
    m_mapPortData.SetAt(dwPort, pPortDate);
    LeaveCriticalSection( &m_cs );
    
    return pPortDate;
}

PORT_DATA * CMainFrame::GetPortDataByPort(int nPort)
{
	PORT_DATA * pPortData = NULL;
	m_mapPortData.Lookup(nPort, pPortData);
	return pPortData;
}
#endif


void CMainFrame::OnStopOnePort(WPARAM wParam,LPARAM lpParam)
{
	UNUSED_ALWAYS(lpParam);

	DWORD dwPort = wParam;
	StopOnePortWork(dwPort);
}


DWORD WINAPI CMainFrame::GetThreadFunc(LPVOID lpParam)
{
	DWORD *pStruct = (DWORD *)lpParam;
	CMainFrame * This = (CMainFrame * )(pStruct[0]);

	DWORD dwPort = pStruct[1];
	return This->ClosePortFunc(dwPort);
}

DWORD CMainFrame::ClosePortFunc(DWORD dwPort)
{
	m_pBMAF->BMAF_StopOneWork(dwPort);

	return 0L;
}
BOOL CMainFrame::CheckDLFiles()
{
	CFileFind finder;	
	CString strTmp = _T("");
	for(int i=0; i< m_nFileCount; i++)
	{
		CString strFile = m_arrFile.GetAt(i);
		if(!strFile.IsEmpty() && strFile.CompareNoCase(FILE_OMIT)!=0)
		{
			if(!finder.FindFile(strFile))
			{
				strTmp += strFile;
				strTmp += _T("\n");
			}
			else
			{
			   finder.FindNextFile();
			   if(finder.GetLength() == 0)
			   {
					strTmp += strFile;
					strTmp += _T("\n");
			   }
			   finder.Close();
			}
		}
	}

	if(!strTmp.IsEmpty())
	{
		CString strError;
		strError.Format(IDS_ERR_FILES_NOT_EXIST,strTmp);
		AfxMessageBox(strError);
		return FALSE;
	}

	return TRUE;
}
BOOL CMainFrame::InitUDiskBufMap()
{
	/*clear UDISK_IMG map*/
	ClearExtImgMap(m_mapUDiskIMg);

	PFILE_INFO_T pFileInfo = NULL;
    int nFileNameLen = UDSIK_IMG_NAME_LEN; // udisk_img_000
	CString strUDiskImgFile;
	int nIdx = m_sheetSettings.GetFileInfo(_T("UDISK_IMG"),(LPDWORD)&pFileInfo);
	if(nIdx != -1 && pFileInfo != NULL)
	{
		strUDiskImgFile = m_arrFile.GetAt(nIdx);
		if(strUDiskImgFile.IsEmpty() || strUDiskImgFile.CompareNoCase(FILE_OMIT)==0)
		{
			// not select UDISK_IMG
			return TRUE;
		}
		CString strDir = strUDiskImgFile;		
		int nFind = strDir.ReverseFind(_T('\\'));
		strDir = strDir.Left(nFind);
		CString strFind = strDir + _T("\\udisk_img_*.bin");	

		WIN32_FIND_DATA wfd = { 0 };
		HANDLE hFind = ::FindFirstFile( strFind, &wfd );
		BOOL bFind = TRUE;
		while( INVALID_HANDLE_VALUE != hFind  && bFind)
		{
			CString strFileName =((CString) (wfd.cFileName)).Left(((CString) (wfd.cFileName)).GetLength() - 4);
			if( strFileName.GetLength() == nFileNameLen)
			{
				int nSectorSize = 0;
				CString strSectorSize = strFileName.Right(3);
				_stscanf(strSectorSize,_T("%03d"),&nSectorSize);
				nSectorSize *= 1024;
				CString strFile;
				strFile.Format(_T("%s\\%s"),strDir,wfd.cFileName);
				EXT_IMG_INFO_PTR pUDisk = new EXT_IMG_INFO;
				_tcscpy(pUDisk->szFilePath,strFile);
				
				CFile file(strFile,CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary);
				pUDisk->dwSize = file.GetLength();
				if(pUDisk->dwSize  != 0 )
				{	
					pUDisk->pBuf = new BYTE[pUDisk->dwSize];
					file.Read(pUDisk->pBuf,pUDisk->dwSize);
				}				
				file.Close();

				m_mapUDiskIMg.SetAt(nSectorSize,pUDisk);
			}

			bFind = ::FindNextFile(hFind, &wfd);
			
		}
		if(INVALID_HANDLE_VALUE != hFind)
		{
			::FindClose(hFind);	
		}
	}

	return TRUE;
}

BOOL CMainFrame::InitNVBuffer()
{
	CString strNVFileType;
	CString strNVFileName;
	PFILE_INFO_T pNVFile = NULL;
	int nIdx = m_sheetSettings.GetFileInfo(_T("NV"),(LPDWORD)&pNVFile);
	if(nIdx != -1 && pNVFile != NULL)
	{
		strNVFileName = m_arrFile.GetAt(nIdx);
	}
	
	if(m_sheetSettings.IsReadFlashInFDL2() || m_sheetSettings.IsHasLang())
	{
		_ASSERTE(!strNVFileName.IsEmpty() && strNVFileName.CompareNoCase(FILE_OMIT) != 0);		
		
		CFile file(strNVFileName,CFile::modeRead | CFile::shareDenyWrite);
		m_dwNvFileSize = file.GetLength();
		if(m_dwNvFileSize != 0 )
		{	
			m_pNVFileBuf = new BYTE[m_dwNvFileSize];
			file.Read(m_pNVFileBuf,m_dwNvFileSize);
		}
		
		file.Close();
		if(m_sheetSettings.IsHasLang() && m_dwNvFileSize != 0)
		{
			DWORD dwOffset = 0;
			DWORD dwLength = 0;
			if(FindNVOffset(NV_MULTI_LANG_ID,m_pNVFileBuf,m_dwNvFileSize,dwOffset,dwLength) &&
				dwLength == sizeof(NV_MULTI_LANGUE_CFG))
			{
				NV_MULTI_LANGUE_CFG *pObj = (NV_MULTI_LANGUE_CFG *)(m_pNVFileBuf+dwOffset);
				for(int k = 0; k<NV_MAX_LANG_NUM;k++)
				{
					BYTE flag = (BYTE)m_sheetSettings.m_pageMultiLang.m_agLangFlag.GetAt(k);
					pObj->flag[k] = flag;
				}
			}
			else
			{
				AfxMessageBox(_T("Not find multi-lang item in NV file!"));
				return FALSE;
			}
		}
	}

	return TRUE;
}

BOOL CMainFrame::InitReportInfo()
{
	CFileFind finder;
	CString strErrMsg;
	_TCHAR szConfigPath[_MAX_PATH]={0};
	_TCHAR szDefaultPath[_MAX_PATH]={0};
	_TCHAR szCustPath[_MAX_PATH]={0};
	::GetModuleFileName(g_theApp.m_hInstance,szConfigPath,_MAX_PATH);
	_tcscpy(szDefaultPath,szConfigPath);
    LPTSTR pResult = _tcsrchr(szConfigPath,_T('.'));
    *pResult = 0;
    _tcscat(szConfigPath,_T(".ini"));
	
	pResult = _tcsrchr(szDefaultPath,_T('\\'));
    *pResult = 0;
    _tcscat(szDefaultPath,_T("\\__report_result.txt"));	
	
	BOOL bEnableReport = GetPrivateProfileInt(_T("Report"),_T("enable"),0,szConfigPath);
	if(bEnableReport)
	{
		GetPrivateProfileString(_T("Report"),_T("path"),szDefaultPath,szCustPath,_MAX_PATH,szConfigPath);
		if(finder.FindFile(szCustPath))
		{
			DWORD dwAtt = 0;
			dwAtt = ::GetFileAttributes(szCustPath);
			dwAtt &= ~FILE_ATTRIBUTE_READONLY;
			::SetFileAttributes(szCustPath,dwAtt);
		}
		
		m_pReportFile = _tfopen(szCustPath,_T("a+"));
		
		if(m_pReportFile == NULL)
		{
			strErrMsg.Format(_T("Open Success-Report file [%s] fail!"),szCustPath);
			AfxMessageBox( strErrMsg);
			return FALSE;
		}
	}

	return TRUE;
}

void CMainFrame::ClearExtImgMap(MAP_EXTIMG &map)
{
	POSITION pos = map.GetStartPosition();
	while(NULL != pos)
	{
		DWORD dwKey= 0;
        EXT_IMG_INFO_PTR pExtImgInfo = NULL;
      
        map.GetNextAssoc( pos, dwKey, pExtImgInfo );

		if(pExtImgInfo != NULL)
		{
			if(pExtImgInfo->pBuf != NULL)
			{
				delete [] pExtImgInfo->pBuf;
				pExtImgInfo->pBuf= NULL;
			}
			delete pExtImgInfo;
		}
	}
	map.RemoveAll();
}

BOOL CMainFrame::InitChipDspBufmap()
{
	/*clear UDISK_IMG map*/
	ClearExtImgMap(m_mapChipDsp);

	if(!m_sheetSettings.IsEnableChipDspMap())
	{
		// need not chip-dsp map
		return TRUE;
	}

	CString strErrMsg =_T("");
	PFILE_INFO_T pFileInfo = NULL;
	CString strChipDspFile;
	int nIdx = m_sheetSettings.GetFileInfo(_T("DSPCode"),(LPDWORD)&pFileInfo);
	if(nIdx != -1 && pFileInfo != NULL)
	{
		strChipDspFile = m_arrFile.GetAt(nIdx);
		if(strChipDspFile.IsEmpty() || strChipDspFile.CompareNoCase(FILE_OMIT)==0)
		{
			// not select "DSPCode"
			return TRUE;
		}

		CFileFind finder;
		
		_TCHAR szConfigPath[_MAX_PATH]={0};
		::GetModuleFileName(g_theApp.m_hInstance,szConfigPath,_MAX_PATH);
		LPTSTR pResult = _tcsrchr(szConfigPath,_T('\\'));
		*pResult = 0;
		_tcscat(szConfigPath,_T("\\BMFileType.ini"));
		
		_TCHAR szKeyValue[ MAX_BUF_SIZE ]={0}; 
		DWORD dwSize = GetPrivateProfileSection( _T("ChipDSPMap"), szKeyValue, MAX_BUF_SIZE, szConfigPath );
		if(dwSize == 0)
		{
			AfxMessageBox(_T("Not found ChipID-DSPName map setting in BMFileType.ini!"));
			return FALSE;
		}
		CStringArray arrKeyData;    
		UINT nFileCount = (UINT)EnumKeys(szKeyValue,&arrKeyData);
		if(nFileCount == 0)
		{
			AfxMessageBox(_T("Not found ChipID-DSPName map setting in BMFileType.ini!"));
			return FALSE;
		}
		
		CString strDir = strChipDspFile;
		
		int nFind = strDir.ReverseFind(_T('\\'));
		strDir = strDir.Left(nFind);

		for(UINT i= 0; i< nFileCount; i++)
		{		
			DWORD dwChipID = 0;
			CString strChipID = arrKeyData[2*i];
			strChipID.MakeUpper();
			_stscanf(strChipID,_T("0X%08X"),&dwChipID);		
			CString strFile;
			strFile.Format(_T("%s\\%s"),strDir,arrKeyData[2*i+1]);
			if(!finder.FindFile(strFile))
			{
				strErrMsg += strFile;
				strErrMsg += _T("\r\n");
				continue;
			}
			EXT_IMG_INFO_PTR pChipDsp = new EXT_IMG_INFO;
			_tcscpy(pChipDsp->szFilePath,strFile);			
			CFile file(strFile,CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary);
			pChipDsp->dwSize = file.GetLength();
			if(pChipDsp->dwSize  != 0 )
			{	
				pChipDsp->pBuf = new BYTE[pChipDsp->dwSize];
				file.Read(pChipDsp->pBuf,pChipDsp->dwSize);
			}				
			file.Close();			
			m_mapChipDsp.SetAt(dwChipID,pChipDsp);			
		}
	}

	if(!strErrMsg.IsEmpty())
	{
		strErrMsg.Insert(0,_T("Not found bellow DSP file:\r\n"));
		strErrMsg += _T("\r\nPlease check BMFileType.ini, [ChipDspMap]!");
		AfxMessageBox(strErrMsg);
		return FALSE;
	}

	return TRUE;
}

void CMainFrame::GetOprErrorCodeDescription(
                                           DWORD dwErrorCode,
                                           LPTSTR lpszErrorDescription, 
                                           int nSize )
{
    if( lpszErrorDescription == NULL || nSize == 0 )
        return;
    
    _TCHAR szKey[ 10 ];
    _itot( dwErrorCode, szKey, 10 );
    
    GetPrivateProfileString(  _T("ErrorDescription"), szKey,
        _T("Unknown Error"), lpszErrorDescription, 
        nSize, m_strOprErrorConfigFile );  
    
    return;
}