// NeroBurn.cpp: implementation of the CNeroBurn class. // ////////////////////////////////////////////////////////////////////// //这个类也是类之间相互引用的一个具体的成功的;例子 #include "stdafx.h" #include "ylgl.h" #include "NeroDlg.h" #include "NeroBurn.h" #include "SelBrunDevice.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// extern CNeroDlg* pDlg; CNeroBurn::CNeroBurn() { NeroBurnOK=false; NeroWorkError=false; #ifdef USE_KERNEL_DLL m_pRootItem = NULL; InitRootItem(); #endif } CNeroBurn::~CNeroBurn() { NeroAPIFree(); for(int i=0; iIdleCallback; nsSettings.nstIdle.ncUserData = pDlg; nsSettings.nstSoftware = pcSoftware; nsSettings.nstUserDialog.ncCallbackFunction = (void*)pDlg->UserDialog; nsSettings.nstUserDialog.ncUserData = pDlg; nsSettings.nstLanguageFile =pcLanguageFile; // npProgress will be used during the burn process npProgress.npAbortedCallback = (NERO_ABORTED_CALLBACK)pDlg->AbortedCallback; npProgress.npAddLogLineCallback = (NERO_ADD_LOG_LINE_CALLBACK)pDlg->AddLogLine; npProgress.npDisableAbortCallback = NULL; npProgress.npProgressCallback = (NERO_PROGRESS_CALLBACK)pDlg->ProgressCallback; npProgress.npSetPhaseCallback = (NERO_SET_PHASE_CALLBACK)pDlg->SetPhaseCallback; npProgress.npUserData = pDlg; npProgress.npSetMajorPhaseCallback=NULL; npProgress.npSubTaskProgressCallback=NULL; m_pndiDeviceInfos = NULL; NEROAPI_INIT_ERROR initErr; initErr = NeroInit(&nsSettings, NULL); switch (initErr) { case NEROAPI_INIT_OK: break; case NEROAPI_INIT_INVALID_ARGS: { AfxMessageBox("无效的参数, 请与系统管理员联系!", MB_ICONSTOP); return 0; } break; case NEROAPI_INIT_INVALID_SERIAL_NUM: { AfxMessageBox("刻录驱动未正确安装, 请与系统管理员联系!", MB_ICONSTOP); return 0; } break; default: { AfxMessageBox("出现未知错误, 请与系统管理员联系!", MB_ICONSTOP); return 0; } break; } // 获取可用的设备; m_pndiDeviceInfos = NeroGetAvailableDrivesEx(m_bDvd ? MEDIA_DVD_ANY : MEDIA_CD, NULL); if (!m_pndiDeviceInfos || m_pndiDeviceInfos->nsdisNumDevInfos == 0) { AfxMessageBox("未找到可用的刻录设备, 请与系统管理员联系!", MB_ICONSTOP); return 0; } return 1; } void CNeroBurn::NeroAPIFree() { if (m_pndiDeviceInfos) { NeroFreeMem(m_pndiDeviceInfos); } NeroClearErrors(); NeroDone(); NeroAPIGlueDone(); return; } // 如果pArray的元素有属于str的子目录或子文件, 将pArray的元素保存到array中; void GetChildArray(CString str, CStringArray *pArray, CStringArray &array) { CString temp; for(int i=0; iGetSize(); i++) { temp=pArray->ElementAt(i); // 截取掉最后一层文件夹,保留前面的; temp=temp.Left(temp.ReverseFind('\\')); if(temp==str) { array.Add (pArray->ElementAt (i)); } } } void GetChildPhotoArray(CString str, CStringArray *pArray, CStringArray &array) { CString temp; for(int i=0; iGetSize (); i++) { temp=pArray->ElementAt (i); // 截取掉最后一层文件夹,保留前面的; temp=temp.Left (temp.ReverseFind ('\\')); if(temp==str) { array.Add (pArray->ElementAt (i)); } } } void CNeroBurn::NeroAPIBurn() { #ifdef USE_KERNEL_DLL DiscBurn(); RemoveRootItem(); return; #endif INT i = 0; // 清空所有NERO_ISO_ITEM元素对象; for( i=0; ifileName,str.Right(str.GetLength()-str.ReverseFind('\\')-1)); strcpy(pMniiFile->sourceFilePath,"c:\\"); #else _tcscpy_s(pMniiFile->fileName, 252, str.Right(str.GetLength()-str.ReverseFind('\\')-1)); _tcscpy_s(pMniiFile->sourceFilePath, 252, "c:\\"); #endif pMniiFile->isDirectory=true; pMniiFile->isReference=false; pMniiFile->unicodeFileName=NULL; if(i==m_DirArray.GetSize ()-1) { pMniiFile->nextItem=NULL; } else {// nextItem指向同类型的元素指针; pMniiFile->nextItem=m_photoMniiArray.ElementAt(i+1); } ////////////////////////// pMniiFile->subDirFirstItem=NULL; ////////////////////////// } // 继续创建根目录以下的文件层和文件; for(i=0;insdisDevInfos[0]; m_ndhDeviceHandle = NeroOpenDevice(nsdiDevice); if (!m_ndhDeviceHandle) { AfxMessageBox("刻录设备不能打开, 请与系统管理员联系!", MB_ICONSTOP); NeroWorkError=true; } else { CString title=g_title+"("+m_strCustomerInfo; title+=")客照"; if(m_bDvd) writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(\ m_photoMniiArray.ElementAt(0),title,NCITEF_USE_JOLIET|NCITEF_CREATE_ISO_FS); else writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(\ m_photoMniiArray.ElementAt(0),title,NCITEF_USE_JOLIET); int iRes; if(m_bDvd) iRes= NeroBurn(m_ndhDeviceHandle, NERO_ISO_AUDIO_MEDIA, &writeCD, NBF_WRITE|NBF_CLOSE_SESSION, 10, &npProgress); else iRes= NeroBurn(m_ndhDeviceHandle, NERO_ISO_AUDIO_CD, &writeCD, NBF_WRITE|NBF_CLOSE_SESSION, 0, &npProgress); //NBF_WRITE|NBF_CLOSE_SESSION NeroFreeIsoTrack(writeCD.nwcdIsoTrack); NeroCloseDevice(m_ndhDeviceHandle); char* Log = NeroGetErrorLog(); switch(iRes) { case NEROAPI_BURN_OK: AfxMessageBox("刻录成功!", MB_ICONINFORMATION); NeroBurnOK=true; break; case NEROAPI_BURN_UNKNOWN_CD_FORMAT: AfxMessageBox("刻录失败:无效刻录盘格式!", MB_ICONSTOP); NeroWorkError=true; //AppendString ("BurnCD() : unknown CD format"); break; case NEROAPI_BURN_INVALID_DRIVE: //AppendString ("BurnCD() : invalid drive"); AfxMessageBox("刻录失败:驱动器无效!", MB_ICONSTOP); NeroWorkError=true; break; case NEROAPI_BURN_FAILED: AfxMessageBox("刻录失败!", MB_ICONSTOP); NeroWorkError=true; //AppendString ("BurnCD() : burn failed"); break; case NEROAPI_BURN_FUNCTION_NOT_ALLOWED: //AppendString ("BurnCD() : function not allowed"); case NEROAPI_BURN_DRIVE_NOT_ALLOWED: //AppendString ("BurnCD() : drive not allowed"); AfxMessageBox("刻录失败:刻录驱动未安装正确!", MB_ICONSTOP); NeroWorkError=true; break; default: AfxMessageBox("刻录失败:未知错误!", MB_ICONSTOP); NeroWorkError=true; //AppendString ("BurnCD() : unknown error"); break; } } } void CNeroBurn::JoinDir(CString dirname) { CString str; if(GetPosFromName(dirname)==-1) {// 如果目录不在m_DirArray中,要先把根目录加进m_nameArray中; NERO_ISO_ITEM *pMniiFile=new NERO_ISO_ITEM; m_photoMniiArray.Add(pMniiFile); m_nameArray.Add(dirname); str=dirname; #if defined(VC80) || defined(VC70) || defined(VC60) strcpy(pMniiFile->fileName,str.Right(str.GetLength()-str.ReverseFind('\\')-1)); strcpy(pMniiFile->sourceFilePath,"c:\\"); #else _tcscpy_s(pMniiFile->fileName, 252, str.Right(str.GetLength()-str.ReverseFind('\\')-1)); _tcscpy_s(pMniiFile->sourceFilePath, 252, "c:\\"); #endif pMniiFile->isDirectory=true; pMniiFile->isReference=false; pMniiFile->unicodeFileName=NULL; pMniiFile->nextItem=NULL; } // dirname这个根目录下的子目录; CStringArray childdirarray; // 子目录下的相片路径; CStringArray childphotoarray; // 将m_pDir中所有dirname的子目录放到childdirarray中; GetChildArray(dirname, m_pDir, childdirarray); // 将dirname目录的所有相片路径保存到childphotoarray中; GetChildPhotoArray(dirname, &(m_pPhotoArray[GetDirPos(dirname)]), childphotoarray); // 获取dirname这个根目录所有子目录个数; int dircount=childdirarray.GetSize (); // 获取dirname这个根目录所有相片张数; int photocount=childphotoarray.GetSize (); // oldcount为尾元素索引; int oldcount=m_photoMniiArray.GetSize(); if( dircount==0 && photocount==0 ) { NERO_ISO_ITEM *pMniiFile=m_photoMniiArray.ElementAt(GetPosFromName(dirname)); pMniiFile->subDirFirstItem=NULL; return; } // 再添加dircount + photocount 个NERO_ISO_ITEM元素; int nn = 0; for( nn=0; nnfileName,str.Right(str.GetLength()-str.ReverseFind('\\')-1)); strcpy(pMniiFile->sourceFilePath,"c:\\"); #else _tcscpy_s(pMniiFile->fileName, 252, str.Right(str.GetLength()-str.ReverseFind('\\')-1)); _tcscpy_s(pMniiFile->sourceFilePath, 252, "c:\\"); #endif pMniiFile->isDirectory=true; pMniiFile->isReference=false; pMniiFile->unicodeFileName=NULL; if(nn==dircount+photocount-1) { pMniiFile->nextItem=NULL; } else { pMniiFile->nextItem=m_photoMniiArray.ElementAt(realpos+oldcount+1); } realpos++; } // 再设置剩余的photocount个元素为文件元素; for(int j=0; jfileName,path.Right(path.GetLength()-path.ReverseFind('\\')-1)); strcpy(pMniiFile->sourceFilePath,path); #else _tcscpy_s(pMniiFile->fileName, 252, path.Right(path.GetLength()-path.ReverseFind('\\')-1)); _tcscpy_s(pMniiFile->sourceFilePath, 252, path); #endif pMniiFile->isDirectory=false; pMniiFile->isReference=false; pMniiFile->unicodeFileName=NULL; if(j==photocount-1) pMniiFile->nextItem=NULL; else pMniiFile->nextItem=m_photoMniiArray.ElementAt(realpos+oldcount+1); realpos++; } int pos=GetPosFromName(dirname); NERO_ISO_ITEM *pMniiFile=m_photoMniiArray.ElementAt(pos); // 设置dirname根元素的NERO_ISO_ITEM的第一个子目录元素指针; pMniiFile->subDirFirstItem=m_photoMniiArray.ElementAt(oldcount); for( nn=0; nnGetSize(); i++) { if(dir==m_pDir->ElementAt(i)) return i; } return -1; } //imapi.exe int CNeroBurn::GetPosFromName(CString dirname) { for(int i=0; iisDirectory = TRUE; m_pRootItem->longFileName = _strdup(_T("光盘根级虚元素")); m_pRootItem->isReference = FALSE; m_pRootItem->unicodeFileName = NULL; m_pRootItem->nextItem = NULL; m_pRootItem->subDirFirstItem = NULL; } return m_pRootItem; } /************************************************************************/ /* 函数:GetDiscItem 描述:返回光盘要刻录的第一个元素。 参数: 返回:返回光盘要刻录的第一个元素。 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::GetDiscItem() { if ( m_pRootItem == NULL) { if ( InitRootItem() == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); return NULL; } } if ( m_pRootItem ) return m_pRootItem->subDirFirstItem; else return NULL; } /************************************************************************/ /* 函数:AddSiblingRootItem 描述:将元素添加到根目录的兄弟链中。 参数: pRootItem[IN]:新的根目录兄弟项; 返回:成功添加返回新项,否则返回NULL; 注意:。 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddSiblingRootItem( IN NERO_ISO_ITEM* pRootItem ) { if ( m_pRootItem == NULL) { if ( InitRootItem() == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); return NULL; } } if ( pRootItem == NULL ) return NULL; if ( m_pRootItem->subDirFirstItem == NULL ) {// 当根元素空时,赋值为第一个值; m_pRootItem->subDirFirstItem = pRootItem; } else { NERO_ISO_ITEM* pNextItem = m_pRootItem->subDirFirstItem; while( pNextItem->nextItem ) pNextItem = pNextItem->nextItem; pNextItem->nextItem = pRootItem; } m_vtItems.push_back(pRootItem); return pRootItem; } /************************************************************************/ /* 函数:AddSiblingRootItem 描述:将元素添加到根目录的兄弟链中。 参数: strRootName[IN]:新的根目录兄弟项名称; bIsDirectory[IN]:新的根目录兄弟项类型; 返回:成功添加返回新项,否则返回NULL 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddSiblingRootItem( IN CString strRootName, IN BOOL bIsDirectory ) { if ( strRootName.IsEmpty() ) { WriteTextLog(_T("获取光盘根目录失败!")); return NULL; } if ( m_pRootItem == NULL) { if ( InitRootItem() == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); return NULL; } } NERO_ISO_ITEM* pRootItem = new NERO_ISO_ITEM; ZeroMemory(pRootItem, sizeof(NERO_ISO_ITEM)); if ( !bIsDirectory ){// 根元素是文件; char path[MAX_PATH]; char* name; GetFullPathName(strRootName, MAX_PATH, path, &name); pRootItem->isDirectory = FALSE; pRootItem->longFileName = _strdup(name); pRootItem->longSourceFilePath = _strdup(path); pRootItem->isReference = FALSE; pRootItem->unicodeFileName = NULL; pRootItem->nextItem = NULL; pRootItem->subDirFirstItem = NULL; }else{ // 根元素是目录; pRootItem->isDirectory = TRUE; pRootItem->longFileName = _strdup(strRootName); pRootItem->isReference = FALSE; pRootItem->unicodeFileName = NULL; pRootItem->nextItem = NULL; pRootItem->subDirFirstItem = NULL; } if ( m_pRootItem->subDirFirstItem == NULL ) { m_pRootItem->subDirFirstItem = pRootItem; } else { NERO_ISO_ITEM* pNextItem = m_pRootItem->subDirFirstItem; while( pNextItem->nextItem ) pNextItem = pNextItem->nextItem; pNextItem->nextItem = pRootItem; } m_vtItems.push_back(pRootItem); return pRootItem; } /************************************************************************/ /* 函数:AddItem2SiblingItem 描述:添加新元素到指定的兄弟项中; 参数: pSiblingItem[IN]: 作为兄弟链的参考兄弟项; pNewItem[IN]:需要添加兄弟链中的新项; 返回: 成功添加返回TRUE,否则返回FALSE; 注意: pSiblingItem不指定具体的类型,如果文件类型(isDirectory==FALSE)或目录类型(isDirectory==TRUE). 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddItem2SiblingItem( IN NERO_ISO_ITEM* pSiblingItem, IN NERO_ISO_ITEM* pNewItem) { if ( m_pRootItem == NULL || m_pRootItem->subDirFirstItem == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddItem2SiblingItem:光盘的根项元素空!\n")); return NULL; } if ( pSiblingItem == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddItem2SiblingItem:光盘的兄弟项元素空!\n")); return NULL; } NERO_ISO_ITEM* pNextItem = pSiblingItem; while(pNextItem->nextItem) { pNextItem = pNextItem->nextItem; } pNextItem->nextItem = pNewItem; pNewItem->nextItem = NULL; m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:AddItem2Path 描述:添加新元素到指定的目录下; 参数: strDiscPath[IN]:光盘目录,作为新元素要父目录; pNewItem[IN]:新元素,将插入到strDiscPath目录下; 返回:成功添加返回TRUE,否则返回FALS; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddItem2Path( IN CString strDiscPath, IN NERO_ISO_ITEM* pNewItem) { if ( m_pRootItem == NULL || m_pRootItem->subDirFirstItem == NULL) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddItem2Path:光盘的根项元素空!\n")); return NULL; } if ( strDiscPath.IsEmpty() ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddItem2Path:光盘的兄弟项元素名称空\n")); return NULL; } // 首先查找; NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath); if ( pTailPathItem == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddItem2Path:未找到光盘指定路径元素:")); OutputDebugString(strDiscPath); return NULL; } pNewItem->nextItem = NULL; if ( pTailPathItem->subDirFirstItem ) { NERO_ISO_ITEM* pNextItem = pTailPathItem->subDirFirstItem; while ( pNextItem->nextItem ) { pNextItem = pNextItem->nextItem; } pNextItem->nextItem = pNewItem; } else { pTailPathItem->subDirFirstItem = pNewItem; } m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:AddSiblingPath 描述:添加新目录到指定的光盘目录的兄弟链尾中; 参数: strDiscPath[IN]:光盘目录,作为新元素兄弟链头路径; strNewPath[IN]:新目录,strDiscPath的兄弟项; 返回: 成功返回TRUE,否则返回FALSE; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddSiblingPath(IN CString strDiscPath, IN CString strNewPath) { // 首先查找; NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath); if ( pTailPathItem == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\nAddPath2Path:未找到光盘指定路径元素:")); OutputDebugString(strDiscPath); return NULL; } NERO_ISO_ITEM* pNewItem = new NERO_ISO_ITEM; ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM)); pNewItem->isDirectory = TRUE; pNewItem->isReference = FALSE; pNewItem->unicodeFileName = NULL; pNewItem->longFileName = _strdup(strNewPath); //sprintf_s(pNewItem->fileName, "%s", strNewPath); pNewItem->subDirFirstItem = NULL; pNewItem->nextItem = NULL; while( pTailPathItem->nextItem ) { pTailPathItem = pTailPathItem->nextItem; } pTailPathItem->nextItem = pNewItem; m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:AddPath 描述:添加新的目录到光盘目录中,若目录不存在,则重新创建目录元素; 参数: strNewPath[IN]:新目录,根目录的新兄弟项; 返回: 成功返回TRUE,否则返回FALSE; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddPath(IN CString strNewPath) { INT nIndex = 0; CString strPath = strNewPath; strPath.TrimRight(_T('\\')); strPath += _T("\\"); NERO_ISO_ITEM* pTailPath = NULL; do { nIndex = strPath.ReverseFind(_T('\\')); if ( nIndex != -1 ) { strPath = strPath.Left(nIndex); pTailPath = FindPathItem(strPath); } else {// 最后一个; pTailPath = FindPathItem(strPath); } } while ( !pTailPath && nIndex != -1); if ( pTailPath == NULL ){// 全新目录; pTailPath = m_pRootItem; strNewPath.TrimRight(_T("\\")); strNewPath += _T("\\"); do { nIndex = strNewPath.Find(_T("\\")); if ( nIndex != -1 ) { if ( pTailPath == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\n添加目录时出错\n")); break; } pTailPath = AddPath2PathItem(pTailPath, strNewPath.Left(nIndex)); strNewPath = strNewPath.Mid(nIndex + 1); } } while ( strNewPath.Find(_T("\\")) != -1 ); } else { if ( strNewPath == strPath ) return pTailPath; strNewPath.Delete(0, strPath.GetLength()+1); strNewPath.TrimRight(_T("\\")); strNewPath += _T("\\"); do { nIndex = strNewPath.Find(_T("\\")); if ( nIndex != -1 ) { if ( pTailPath == NULL ) { WriteTextLog(_T("获取光盘根目录失败!")); OutputDebugString(_T("\n添加目录时出错\n")); break; } pTailPath = AddPath2PathItem(pTailPath, strNewPath.Left(nIndex)); strNewPath = strNewPath.Mid(nIndex + 1); } } while ( strNewPath.Find(_T("\\")) != -1 ); } return pTailPath; } /************************************************************************/ /* 函数:AddPath2Path 描述:添加新目录到指定的光盘目录下; 参数: strDiscPath[IN]:光盘目录,作为新元素要父目录; strNewPath[IN]:新目录,将插入到strDiscPath目录下; 返回: 成功返回TRUE,否则返回FALSE; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddPath2Path(IN CString strDiscPath, IN CString strNewPath) { // 首先查找; NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath); if ( pTailPathItem == NULL ) { WriteTextLog(_T("AddPath2Path:无光盘目录")); OutputDebugString(_T("\nAddPath2Path:未找到光盘指定路径元素:")); OutputDebugString(strDiscPath); return NULL; } NERO_ISO_ITEM* pNewItem = new NERO_ISO_ITEM; ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM)); pNewItem->isDirectory = TRUE; pNewItem->isReference = FALSE; pNewItem->unicodeFileName = NULL; pNewItem->longFileName = _strdup(strNewPath); //sprintf_s(pNewItem->fileName, "%s", strNewPath); pNewItem->subDirFirstItem = NULL; pNewItem->nextItem = NULL; if ( pTailPathItem->subDirFirstItem ) { NERO_ISO_ITEM* pNextItem = pTailPathItem->subDirFirstItem; while ( pNextItem->nextItem ) { pNextItem = pNextItem->nextItem; } pNextItem->nextItem = pNewItem; } else { pTailPathItem->subDirFirstItem = pNewItem; } m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:AddPath2PathItem 描述:添加新目录到指定的光盘目录下; 参数: pPathItem[IN]:光盘目录,作为新元素要父目录; strNewPath[IN]:新目录,将插入到strDiscPath目录下; 返回: 成功返回TRUE,否则返回FALSE; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddPath2PathItem(IN NERO_ISO_ITEM* pPathItem, IN CString strNewPath ) { if ( pPathItem == NULL || pPathItem->isDirectory == FALSE ) { WriteTextLog(_T("AddPath2PathItem:目录元素空或非目录元素!")); return NULL; } NERO_ISO_ITEM* pNewItem = new NERO_ISO_ITEM; ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM)); pNewItem->isDirectory = TRUE; pNewItem->isReference = FALSE; pNewItem->unicodeFileName = NULL; pNewItem->longFileName = _strdup(strNewPath); //sprintf_s(pNewItem->fileName, "%s", strNewPath); pNewItem->subDirFirstItem = NULL; pNewItem->nextItem = NULL; m_vtItems.push_back(pNewItem); if ( pPathItem->subDirFirstItem == NULL ) return pPathItem->subDirFirstItem = pNewItem; NERO_ISO_ITEM* pNextItem = pPathItem->subDirFirstItem; while( pNextItem->nextItem) { pNextItem = pNextItem->nextItem; } return pNextItem->nextItem = pNewItem; } /************************************************************************/ /* 函数:AddFile2Path 描述:添加新文件到指定的光盘目录下; 参数: strDiscPath[IN]:光盘目录,作为新元素的父目录; strFileName[IN]:新文件,将插入到strDiscPath目录下; 返回: 成功返回TRUE,否则返回FALSE; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddFile2Path(IN CString strDiscPath, IN CString strFileName) { // 首先查找; NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath); if ( pTailPathItem == NULL ) { pTailPathItem = AddPath(strDiscPath); if ( pTailPathItem == NULL ) { WriteTextLog(_T("AddFile2Path:获取目录项尾元素失败!")); OutputDebugString(_T("\nAddFile2Path:未找到光盘指定路径元素:")); OutputDebugString(strDiscPath); return NULL; } } NERO_ISO_ITEM* pNewItem = new NERO_ISO_ITEM; ZeroMemory(pNewItem, sizeof(NERO_ISO_ITEM)); pNewItem->isDirectory = FALSE; pNewItem->isReference = FALSE; pNewItem->unicodeFileName = NULL; char path[MAX_PATH]; char* name; GetFullPathName(strFileName, MAX_PATH, path, &name); pNewItem->longFileName = _strdup(name); pNewItem->longSourceFilePath = _strdup(path); //sprintf_s(pNewItem->fileName,"%s", strFileName); pNewItem->nextItem = NULL; pNewItem->subDirFirstItem = NULL; if ( pTailPathItem->subDirFirstItem ) { NERO_ISO_ITEM* pNextItem = pTailPathItem->subDirFirstItem; while ( pNextItem->nextItem ) { pNextItem = pNextItem->nextItem; } pNextItem->nextItem = pNewItem; } else { pTailPathItem->subDirFirstItem = pNewItem; } m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:AddFile2SiblingItem 描述:将文件添加到指定的兄弟项中; 参数: pSiblingItem[IN]: strFileName[IN]: 返回: 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::AddFile2SiblingItem(IN NERO_ISO_ITEM* pSiblingItem, IN CString strFileName) { if (pSiblingItem == NULL) { WriteTextLog(_T("AddFile2SiblingItem:树兄弟项空!")); OutputDebugString(_T("\nAddFile2SiblingItem:树兄弟项出错!\n")); return NULL; } NERO_ISO_ITEM* pNewItem = new NERO_ISO_ITEM; ZeroMemory(pNewItem, sizeof(NERO_ISO_ITEM)); pNewItem->isDirectory = FALSE; pNewItem->isReference = FALSE; char path[MAX_PATH]; char* name; GetFullPathName(strFileName, MAX_PATH, path, &name); pNewItem->longFileName = _strdup(name); pNewItem->longSourceFilePath = _strdup(path); //sprintf_s(pNewItem->fileName,"%s",strFileName); pNewItem->nextItem = NULL; pNewItem->subDirFirstItem = NULL; NERO_ISO_ITEM* pNextItem = pSiblingItem; while(pNextItem->nextItem) { pNextItem = pNextItem->nextItem; } pNextItem->nextItem = pNewItem; m_vtItems.push_back(pNewItem); return pNewItem; } /************************************************************************/ /* 函数:FindPathItem 描述:查找指定的光盘目录,返回目录元素指针对象; 参数: strDiscPath[IN]:要查找的光盘目录,格式如下:"光盘根目录\子目录1\子目录2\子目录3"; 返回: 若存在该光盘目录,则返回该目录元素对象的指针(返回最后一层目录名对应的元素指针),否则返回NULL; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::FindPathItem( IN CString strDiscPath ) { if (strDiscPath.IsEmpty()) { WriteTextLog(_T("FindPathItem:光盘目录参数空!")); return NULL; } if ( m_pRootItem == NULL || m_pRootItem->subDirFirstItem == NULL) { WriteTextLog(_T("FindPathItem:光盘根目录元素空!")); return NULL; } INT nIndex = 0; CStringArray AryLayerName; strDiscPath.TrimRight(_T('\\')); strDiscPath += _T("\\"); do { nIndex = strDiscPath.Find(_T("\\")); if ( nIndex != -1 ) { AryLayerName.Add(strDiscPath.Left(nIndex)); strDiscPath = strDiscPath.Mid(nIndex+1); } } while ( strDiscPath.Find(_T("\\")) != -1 ); NERO_ISO_ITEM *pTailItem = NULL; NERO_ISO_ITEM *pNextItem = m_pRootItem->subDirFirstItem; for ( nIndex = 0; nIndex < AryLayerName.GetSize(); nIndex++ ) { pTailItem = FindPathInSibling(pNextItem, AryLayerName.ElementAt(nIndex)); if ( pTailItem == NULL ) { break; } else { pNextItem = pTailItem->subDirFirstItem; } } if ( (AryLayerName.GetSize() == nIndex) && pTailItem ) { return pTailItem; } return NULL; } /************************************************************************/ /* 函数:FindSiblingPath 描述:在指定的兄弟链中(以及兄弟链中的子链),从兄弟链头元素开始查找指定目录名的元素指针; 参数: pSiblingHeadItem[IN]:兄弟链的头元素,作为查找时的开始位置; strDiscPath[IN]:要在兄弟链中(以及兄弟链中的子链)查找的目录名(只是单层目录名)。 返回: 成功在兄弟链中(以及兄弟链中的子链)查找到该目录名元素,返回该元素对象指针;若未查找到,返回NULL; 注意: 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::FindPathInSibling( IN NERO_ISO_ITEM* pSiblingHeadItem, IN CString& strDiscPath ) { if ( pSiblingHeadItem == NULL ) { WriteTextLog(_T("FindPathInSibling兄弟结点空!")); return NULL; } BOOL bFind = FALSE; NERO_ISO_ITEM* pNextItem = pSiblingHeadItem; do { if (pNextItem->isDirectory) { if ( strDiscPath.CompareNoCase(pNextItem->longFileName) == 0 ) { bFind = TRUE; break; } } pNextItem = pNextItem->nextItem; } while ( pNextItem ); return bFind ? pNextItem : NULL; } /************************************************************************/ /* 函数:FindSiblingNextToLast 描述:返回兄弟链中的倒数第二个元素或者最后一个; 参数: pSiblingHeadItem[IN] 兄弟链的头元素; 返回: 返回兄弟链中的倒数第二个元素或者最后一个; 注意:当兄弟链的只有一个元素时,返回的是本身,也是最后一个; 示例: */ /************************************************************************/ NERO_ISO_ITEM* CNeroBurn::FindSiblingNextToLast( IN NERO_ISO_ITEM* pSiblingHeadItem ) { if ( pSiblingHeadItem == NULL || pSiblingHeadItem->nextItem == NULL ) { return pSiblingHeadItem; } NERO_ISO_ITEM* pSiblingTail = pSiblingHeadItem; while ( pSiblingTail->nextItem->nextItem ) { pSiblingTail = pSiblingTail->nextItem; } return pSiblingTail; } /************************************************************************/ /* 函数:RemoveRootItem 描述:删除整个光盘项; 参数: 返回: 注意: 示例: */ /************************************************************************/ void CNeroBurn::RemoveRootItem() { RemoveAllItem(m_pRootItem); if (m_pRootItem) { if(m_pRootItem->longFileName != NULL) free((void*)m_pRootItem->longFileName), m_pRootItem->longFileName = NULL; if(m_pRootItem->longSourceFilePath != NULL) free((void*)m_pRootItem->longSourceFilePath), m_pRootItem->longSourceFilePath = NULL; delete m_pRootItem; m_pRootItem = NULL; } } /************************************************************************/ /* 函数:RemoveAllItem 描述:删除指定根结点的全部元素; 参数: 返回: 注意: 示例: */ /************************************************************************/ void CNeroBurn::RemoveAllItem(IN NERO_ISO_ITEM* pRootItem) { #if 1 for( vector::iterator it = m_vtItems.begin(); it != m_vtItems.end();) { NERO_ISO_ITEM *pItem = *it; it = m_vtItems.erase(it); if(pItem->longFileName != NULL) free((void*)pItem->longFileName), pItem->longFileName = NULL; if(pItem->longSourceFilePath != NULL) free((void*)pItem->longSourceFilePath), pItem->longSourceFilePath = NULL; delete pItem; pItem = NULL; } return; #else if( pRootItem == NULL ){ WriteTextLog(_T("RemoveChildItem:删除出错!")); OutputDebugString(_T("\nRemoveChildItem:删除出错,!\n")); return; } if ( pRootItem->subDirFirstItem == NULL && pRootItem->nextItem == NULL ){// 最后一个元素; //OutputDebugString(_T("\nRemoveAllItem:目录元素\n")); return; } NERO_ISO_ITEM* pNext2Last = NULL; do { // 查找到兄弟链中的倒第二个(或者最后一个); pNext2Last = FindSiblingNextToLast(pRootItem->subDirFirstItem); NERO_ISO_ITEM* pTailItem = pNext2Last->nextItem; if ( pTailItem ) {// 倒数第二个; if (pTailItem->isDirectory) { RemoveAllItem(pTailItem); } pNext2Last->nextItem = NULL; if(!pTailItem->isReference) { if(pTailItem->longFileName != NULL) free((void*)pTailItem->longFileName), pTailItem->longFileName = NULL; if(pTailItem->longSourceFilePath != NULL) free((void*)pTailItem->longSourceFilePath), pTailItem->longSourceFilePath = NULL; } delete pTailItem; pTailItem = NULL; } else {// 第一个(也是最后一个); if ( pNext2Last->isDirectory ) { RemoveAllItem(pNext2Last); } if(!pNext2Last->isReference) { if(pNext2Last->longFileName != NULL) free((void*)pNext2Last->longFileName), pNext2Last->longFileName = NULL; if(pNext2Last->longSourceFilePath != NULL) free((void*)pNext2Last->longSourceFilePath), pNext2Last->longSourceFilePath = NULL; } delete pNext2Last; pNext2Last = NULL; pRootItem->subDirFirstItem = NULL; } }while( pRootItem->subDirFirstItem ); #endif } void CNeroBurn::DiscBurn() { // 使用第一个设备来刻录;; NERO_SCSI_DEVICE_INFO* nsdiDevice = &m_pndiDeviceInfos->nsdisDevInfos[0]; // 打开设备; m_ndhDeviceHandle = NeroOpenDevice(nsdiDevice); if (!m_ndhDeviceHandle) { AfxMessageBox(_T("刻录设备不能打开, 请与系统管理员联系!"), MB_ICONSTOP); NeroWorkError = true; return; } // 读取CD或DVD媒体信息; NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(m_ndhDeviceHandle, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC); if ( pNeroCDInfo == NULL ) { AfxMessageBox(_T("获取光盘失败, 请与系统管理员联系!"), MB_ICONSTOP); NeroWorkError = true; return; } // 光盘不可写; if ( !pNeroCDInfo->ncdiIsWriteable ) { AfxMessageBox(_T("光盘不可写, 请更换新的光盘!"), MB_ICONSTOP); NeroWorkError = true; return; } #if 0 // 光盘文件系统格式(但是,好像没有用, 估计是SDK版本太老); // pNeroCDInfo->ncdiTrackInfos[0].ntiFSType; // NTFST_UDF DVD格式刻录; NTFST_CDRFS CD格式刻录; if ( m_bDvd && pNeroCDInfo->ncdiTrackInfos[0].ntiFSType == NTFST_CDRFS ) { AfxMessageBox(_T("所选DVD格式刻录,但光盘文件系统是CD格式,请更换DVD文件系统(UDF或新)的光盘!"), MB_ICONSTOP); NeroWorkError = true; return; } if ( !m_bDvd && pNeroCDInfo->ncdiTrackInfos[0].ntiFSType == NTFST_UDF ) { AfxMessageBox(_T("所选DVD格式刻录,但光盘文件系统是CD格式,请更换DVD文件系统(UDF或新)的光盘!"), MB_ICONSTOP); NeroWorkError = true; return; } #endif // 设置写CD参数 ; NERO_WRITE_CD writeCD; memset(&writeCD,0,sizeof(writeCD)); writeCD.nwcdpCDStamp = NULL; writeCD.nwcdArtist = NULL; writeCD.nwcdTitle = NULL; writeCD.nwcdCDExtra = FALSE; writeCD.nwcdNumTracks = 0; // writeCD.nwcdMediaType = m_bDvd ? MEDIA_DVD_ANY : MEDIA_CD; // 这里不是按光盘的媒体类型来赋值; writeCD.nwcdMediaType = pNeroCDInfo->ncdiMediaType; CString title = g_title+ _T("(") + m_strCustomerInfo; title += _T(")客照"); if ( true ) {// 追加方式刻录; NERO_IMPORT_DATA_TRACK_INFO nidtInfo; NERO_IMPORT_DATA_TRACK_RESULT nidtResult; // Prepare the struct. CString csUserMsg = ""; memset(&nidtInfo, 0, sizeof(nidtInfo)); nidtInfo.nidtiSize = sizeof(nidtInfo); void* pCDStamp = NULL; NERO_ISO_ITEM* pniiItem = NULL; pniiItem = NeroImportDataTrack(m_ndhDeviceHandle, pNeroCDInfo->ncdiNumTracks - 1, &pCDStamp, &nidtInfo, 0, &nidtResult, NULL); // If there is a volume name after import, print it out. if(nidtInfo.nidtipVolumeName != NULL) { csUserMsg.Format("Imported volume name: %s", nidtInfo.nidtipVolumeName); //AppendString(csUserMsg); NeroFreeMem (nidtInfo.nidtipVolumeName); } // If there was an error during import, let the user know about it. if((nidtResult != NIDTR_NO_ERROR) || (pniiItem == NULL)) { static LPCSTR errors[] = {"an unknown error","a generic error","a drive error","a read error","a filesystem error","an invalid track number"}; if (nidtResult > NIDTR_INVALID_TRACKNUMBER) nidtResult = NIDTR_NO_ERROR; csUserMsg.Format("There was %s while importing the track!", errors[nidtResult]); //AppendString(csUserMsg); } else if(m_pRootItem->subDirFirstItem != NULL) { if(MergeIsoTracks(&m_pRootItem->subDirFirstItem, pniiItem)) // Merge the new track with the existing one. writeCD.nwcdpCDStamp = pCDStamp; else { //AppendString("There was an error while merging tracks!"); if(pCDStamp != NULL) NeroFreeCDStamp(pCDStamp), pCDStamp = NULL; } } } writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_pRootItem->subDirFirstItem,title,NCITEF_USE_JOLIET|NCITEF_CREATE_ISO_FS); // 以追回的方式刻录 : 使用MEDIA_DVD_ANY 或 MEDIA_CD时, NERO_CD_FORMAT固定为NERO_ISO_AUDIO_MEDIA; int iRes = NeroBurn(m_ndhDeviceHandle, NERO_ISO_AUDIO_MEDIA, &writeCD, NBF_WRITE|NBF_CLOSE_SESSION, 0/*Maximum*/, &npProgress); // 释放媒体资源; NeroFreeMem(pNeroCDInfo); // free memory that was allocated for the track if(writeCD.nwcdIsoTrack != NULL) NeroFreeIsoTrack(writeCD.nwcdIsoTrack); // Free the NERO_WRITE_CD struct too if(writeCD.nwcdpCDStamp != NULL) NeroFreeCDStamp(writeCD.nwcdpCDStamp), writeCD.nwcdpCDStamp = NULL; NeroCloseDevice(m_ndhDeviceHandle); char* Log = NeroGetErrorLog(); switch(iRes) { case NEROAPI_BURN_OK: AfxMessageBox(_T("刻录成功!"), MB_ICONINFORMATION); NeroBurnOK=true; break; case NEROAPI_BURN_UNKNOWN_CD_FORMAT: AfxMessageBox(_T("刻录失败:无效刻录盘格式!"), MB_ICONSTOP); NeroWorkError=true; break; case NEROAPI_BURN_INVALID_DRIVE: AfxMessageBox(_T("刻录失败:驱动器无效!"), MB_ICONSTOP); NeroWorkError=true; break; case NEROAPI_BURN_FAILED: AfxMessageBox(_T("刻录失败!"), MB_ICONSTOP); NeroWorkError=true; break; case NEROAPI_BURN_FUNCTION_NOT_ALLOWED: case NEROAPI_BURN_DRIVE_NOT_ALLOWED: AfxMessageBox(_T("刻录失败:刻录驱动未安装正确!"), MB_ICONSTOP); NeroWorkError=true; break; default: AfxMessageBox(_T("刻录失败:未知错误!"), MB_ICONSTOP); NeroWorkError=true; break; } } inline LPCSTR GetFilename(const NERO_ISO_ITEM* pItem) { return (pItem->longFileName != NULL)? pItem->longFileName : pItem->fileName; } // The following function performs a merge operation between two iso item trees. // The second tree is added onto the first one and the extra items are deleted. // As we do not allow to add directories in our file list we do not make recursive // calls of this method. BOOL CNeroBurn::MergeIsoTracks(NERO_ISO_ITEM** ppniiTarget, NERO_ISO_ITEM* pniiToAdd) { BOOL bResult = ((ppniiTarget != NULL) && (*ppniiTarget != NULL) && (pniiToAdd != NULL)); // Two loops. Outer loops the first tree, the inner loops the second tree. for( ; bResult && (*ppniiTarget != NULL); ppniiTarget = &(*ppniiTarget)->nextItem) { for(NERO_ISO_ITEM** ppniiToAddLocal = &pniiToAdd; *ppniiToAddLocal != NULL; ) { // Compare entry names... if(0 == stricmp(GetFilename(*ppniiTarget), GetFilename(*ppniiToAddLocal))) { // If there is a file name conflict between iso items that belong to imported sessions // always replace the old files in terms of modification times. time_t timeTarget = mktime(&(*ppniiTarget)->entryTime); if(timeTarget == (time_t)-1) { HANDLE hFile = NULL; // handle to file FILETIME ftCreationTime; // creation time FILETIME ftLastAccessTime; // last access time FILETIME ftLastWriteTime; // last write time hFile = CreateFileA((*ppniiTarget)->longSourceFilePath, // open the file to get handle GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template if(hFile == INVALID_HANDLE_VALUE) { CString csMsg; csMsg.Format("Could not open file: %s.", (*ppniiTarget)->longSourceFilePath); //AppendString(csMsg); // show error } else if(GetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime)) timeTarget = CTime(ftLastWriteTime).GetTime(); if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile), hFile = NULL; } time_t timeToAdd = mktime(&(*ppniiToAddLocal)->entryTime); // If we have to replace one item, we will now switch places of items in the first and second tree. // Since one of the items has to be deleted eventually, this operation will // essentially keep the item from the second tree and delete the item from the first tree. if(timeTarget < timeToAdd) { NERO_ISO_ITEM* pniiTmpItem = *ppniiToAddLocal; *ppniiToAddLocal = *ppniiTarget; *ppniiTarget = pniiTmpItem; pniiTmpItem = (*ppniiToAddLocal)->nextItem; (*ppniiToAddLocal)->nextItem = (*ppniiTarget)->nextItem; (*ppniiTarget)->nextItem = pniiTmpItem; } // Remove the item from the second tree. NERO_ISO_ITEM* pniiTmpItem = *ppniiToAddLocal; *ppniiToAddLocal = pniiTmpItem->nextItem; pniiTmpItem->nextItem = NULL; DeleteIsoItemTree(pniiTmpItem); } else // No match, advance to the next item. ppniiToAddLocal = &(*ppniiToAddLocal)->nextItem; } } // Attach whatever is left of the new tree to the main tree. *ppniiTarget = pniiToAdd; // Returning true means, everything is fine, continue. return bResult; } // This function deletes the iso tree recursively. void CNeroBurn::DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem) { // First free our own long filename strings, then free the whole tree. FreeOurOwnResources(pniiItem); NeroFreeIsoItemTree(pniiItem); } void CNeroBurn::FreeOurOwnResources(NERO_ISO_ITEM* pniiItem) { // Step through the tree until the ISO item tree pointer becomes NULL while(pniiItem != NULL) { NERO_ISO_ITEM* pniiNextItem = pniiItem->nextItem; // We have encountered another ISO item tree; recurse another level. if(pniiItem->isDirectory) FreeOurOwnResources (pniiItem->subDirFirstItem); if(!pniiItem->isReference) { if(pniiItem->longFileName != NULL) free((void*)pniiItem->longFileName), pniiItem->longFileName = NULL; if(pniiItem->longSourceFilePath != NULL) free((void*)pniiItem->longSourceFilePath), pniiItem->longSourceFilePath = NULL; } pniiItem = pniiNextItem; } } /************************************************************************/ /* 函数:获取读写速度[3/22/2018 Jeff]; /* 描述:; /* 参数:; /* [IN] :; /* [OUT] :; /* [IN/OUT] :; /* 返回:void; /* 注意:必须在外部释放NeroFreeMem(pnsiWrite); /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ NERO_SPEED_INFOS *CNeroBurn::GetAvailableSpeeds(bool IsWriteSpeed /*= true*/) { // 获取媒体信息; NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(m_ndhDeviceHandle, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC); if ( pNeroCDInfo == NULL ) return NULL; NERO_SPEED_INFOS *pnsiWrite = NeroGetAvailableSpeeds(m_ndhDeviceHandle,IsWriteSpeed ? ACCESSTYPE_WRITE :ACCESSTYPE_READ, pNeroCDInfo->ncdiMediaType,NULL); // 释放媒体资源; NeroFreeMem(pNeroCDInfo); return pnsiWrite; } #endif