NeroImpl.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. #include "StdAfx.h"
  2. #include "NeroImpl.h"
  3. CDialog* CNeroImpl::m_pDailog = NULL;
  4. IdleCallback CNeroImpl::m_pIdelCallback = NULL;
  5. UserDialog CNeroImpl::m_pUserDialog = NULL;
  6. ProgressCallback CNeroImpl::m_pProgressCallback = NULL;
  7. ProgressCallback CNeroImpl::m_pSubTaskProgressCallback = NULL;
  8. AbortedCallback CNeroImpl::m_pAbortedCallback = NULL;
  9. AddLogLine CNeroImpl::m_pAddLogLine = NULL;
  10. SetPhaseCallback CNeroImpl::m_pSetPhaseCallback = NULL;
  11. DisableAbortCallback CNeroImpl::m_pDisableAbortCallback = NULL;
  12. SetMajorPhaseCallback CNeroImpl::m_pSetMajorPhaseCallback = NULL;
  13. WriteIOCallback CNeroImpl::m_pWriteIOCallback = NULL;
  14. ReadIOCallback CNeroImpl::m_pReadIOCallback = NULL;
  15. EOFCallback CNeroImpl::m_pEOFCallback = NULL;
  16. ErrorCallback CNeroImpl::m_pErrorCallback = NULL;
  17. CNeroImpl::CNeroImpl(void) :m_nRef(0)
  18. , m_pNeroDeviceInfos(NULL)
  19. , m_bInited(false)
  20. {
  21. }
  22. CNeroImpl::~CNeroImpl(void)
  23. {
  24. if (m_pNeroDeviceInfos)
  25. {
  26. NeroFreeMem(m_pNeroDeviceInfos);
  27. }
  28. NeroClearErrors();
  29. NeroDone();
  30. NeroAPIGlueDone();
  31. }
  32. ULONG CNeroImpl::AddRef()
  33. {
  34. InterlockedIncrement(&m_nRef);
  35. return m_nRef;
  36. }
  37. ULONG CNeroImpl::Release()
  38. {
  39. LONG ulRefCount = InterlockedDecrement(&m_nRef);
  40. //如果为0,删除对象;
  41. if (m_nRef == 0)
  42. {
  43. delete this;
  44. }
  45. return ulRefCount;
  46. }
  47. HRESULT CNeroImpl::QueryInterface(REFIID riid, __RPC__deref_out void **ppvObject)
  48. {
  49. if (!ppvObject)
  50. return E_INVALIDARG;
  51. *ppvObject = NULL;
  52. if (riid == IID_IUnknown || riid == IID_IBurndisc)
  53. {
  54. *ppvObject = (LPVOID)this;
  55. AddRef();
  56. return NOERROR;
  57. }
  58. return E_NOINTERFACE;
  59. }
  60. bool CNeroImpl::Initialize()
  61. {
  62. // 加载Nero的库;
  63. if (!NeroAPIGlueConnect(NULL)) {
  64. m_strLastError = _T("连接NeroSDK失败!");
  65. return false;
  66. }
  67. // 获取Nero库版本信息;
  68. WORD ver1, ver2, ver3, ver4;
  69. if (!NeroGetAPIVersionEx(&ver1, &ver2, &ver3, &ver4, NULL)) {
  70. m_strLastError = _T("获取Nero Version失败!");
  71. return false;
  72. }
  73. // 初始化Nero环境(参数固定);
  74. strcpy_s(m_pcNeroFilesPath, 128, "NeroFiles");
  75. strcpy_s(m_pcVendor, 128, "nero");
  76. strcpy_s(m_pcSoftware, 128, "Nero - Burning Rom");
  77. strcpy_s(m_pcLanguageFile, 128, "Nero.txt");
  78. m_NeroSettings.nstNeroFilesPath = m_pcNeroFilesPath;
  79. m_NeroSettings.nstVendor = m_pcVendor;
  80. m_NeroSettings.nstIdle.ncCallbackFunction = CNeroImpl::m_pIdelCallback;
  81. m_NeroSettings.nstIdle.ncUserData = CNeroImpl::m_pDailog;
  82. m_NeroSettings.nstSoftware = m_pcSoftware;
  83. m_NeroSettings.nstUserDialog.ncCallbackFunction = CNeroImpl::m_pUserDialog;
  84. m_NeroSettings.nstUserDialog.ncUserData = CNeroImpl::m_pDailog;
  85. m_NeroSettings.nstLanguageFile = m_pcLanguageFile;
  86. // 初始化;
  87. NEROAPI_INIT_ERROR Err = NeroInit(&m_NeroSettings, NULL);
  88. switch (Err)
  89. {
  90. case NEROAPI_INIT_OK:
  91. m_strLastError = _T("初始化Nero成功!");
  92. break;
  93. case NEROAPI_INIT_INVALID_ARGS:
  94. m_strLastError = _T("NeroInit() : invalid args");
  95. break;
  96. case NEROAPI_INIT_INVALID_SERIAL_NUM:
  97. m_strLastError = _T("NeroInit() : invalid serial number");
  98. break;
  99. case NEROAPI_INIT_DEMOVERSION_EXPIRED:
  100. m_strLastError = _T("NeroInit() : demo version has expired");
  101. break;
  102. case NEROAPI_INIT_CANNOT_LOCK:
  103. m_strLastError = _T("NeroInit() : cannot lock");
  104. break;
  105. case NEROAPI_INIT_UNSPECIFIED_ERROR:
  106. m_strLastError = _T("NeroInit() : unspecified error");
  107. break;
  108. default:
  109. break;
  110. }
  111. m_NeroProgress.npProgressCallback = m_pProgressCallback;
  112. m_NeroProgress.npAbortedCallback = m_pAbortedCallback;
  113. m_NeroProgress.npAddLogLineCallback = m_pAddLogLine;
  114. m_NeroProgress.npSetPhaseCallback = m_pSetPhaseCallback;
  115. m_NeroProgress.npUserData = this;
  116. m_NeroProgress.npDisableAbortCallback = m_pDisableAbortCallback;
  117. m_NeroProgress.npSetMajorPhaseCallback = m_pSetMajorPhaseCallback;
  118. m_NeroProgress.npSubTaskProgressCallback = m_pSubTaskProgressCallback;
  119. return m_bInited = (Err == NEROAPI_INIT_OK ? true : false);
  120. }
  121. int CNeroImpl::GetAvailableDrives()
  122. {
  123. if (!m_bInited)
  124. return 0;
  125. // 清除之前的;
  126. m_vtDevInfo.clear();
  127. if (m_pNeroDeviceInfos)
  128. NeroFreeMem(m_pNeroDeviceInfos);
  129. // 参数一没什么意义,可以填MEDIA_NONE,MEDIA_CD或MEDIA_DVD_ANY;
  130. m_pNeroDeviceInfos = NeroGetAvailableDrivesEx(MEDIA_NONE, NULL);
  131. // 遍历设备;
  132. if (m_pNeroDeviceInfos)
  133. {
  134. char szDevName[MAX_PATH] = { 0 };
  135. for (int i = 0; i < m_pNeroDeviceInfos->nsdisNumDevInfos; i++)
  136. {
  137. if (strcmp(m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterName, "Virtual") != 0)
  138. {
  139. DeviceInfo devinfo;
  140. devinfo.nIndex = i;
  141. sprintf_s(szDevName, "%c:\\%s", m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter, m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceName);
  142. #ifdef UNICODE
  143. int nLen = strlen(szDevName);
  144. devinfo.strDevName.append((TCHAR*)(convert("GBK", "UCS-2LE", szDevName, nLen).c_str()), nLen);
  145. #else
  146. devinfo.strDevName = szDevName;
  147. #endif
  148. devinfo.pDevInfo = &m_pNeroDeviceInfos->nsdisDevInfos[i];
  149. m_vtDevInfo.push_back(devinfo);
  150. }
  151. }
  152. }
  153. return m_pNeroDeviceInfos ? m_pNeroDeviceInfos->nsdisNumDevInfos : 0;
  154. }
  155. void* CNeroImpl::GetDeivceInfo(int nIndex)
  156. {
  157. if (m_vtDevInfo.size() == 0 || nIndex > m_vtDevInfo.size())
  158. return NULL;
  159. return &m_vtDevInfo.at(nIndex);
  160. }
  161. void* CNeroImpl::GetDeivceInfo(const TCHAR *pszDevName)
  162. {
  163. for (vector<DeviceInfo>::iterator it = m_vtDevInfo.begin(); it != m_vtDevInfo.end(); it++)
  164. {
  165. if (_tcscmp(pszDevName, it->strDevName.c_str()) == 0)
  166. {
  167. return &(*it);//或return &m_vtDevInfo.at(it - m_vtDevInfo.begin());
  168. }
  169. }
  170. return NULL;
  171. }
  172. void CNeroImpl::AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles)
  173. {
  174. bool IsNullPath = false;
  175. NERO_ISO_ITEM* pHeadItem = NULL;
  176. NERO_ISO_ITEM* pNextItem = NULL;
  177. if (strFatherNode.size() == 0)
  178. {//所有文件,都加到根目录下;
  179. IsNullPath = true;
  180. pHeadItem = m_BurnItem.FindLastItemInSibling(m_BurnItem.GetHeadItem());
  181. if (pHeadItem == NULL)
  182. pHeadItem = m_BurnItem.GetVirtualItem();
  183. }
  184. else
  185. {
  186. pHeadItem = m_BurnItem.FindPathItem(strFatherNode);
  187. if (!pHeadItem)
  188. {// 新添根结点;
  189. pHeadItem = m_BurnItem.AddPath(strFatherNode);
  190. pHeadItem->isDirectory = TRUE;
  191. }
  192. else
  193. {
  194. // 找到尾结点;
  195. pNextItem = m_BurnItem.FindLastItemInSibling(pHeadItem->subDirFirstItem);
  196. }
  197. }
  198. if (pHeadItem)
  199. {
  200. if (!IsNullPath)
  201. {
  202. for (vector<TString>::iterator it = vtfiles.begin(); it != vtfiles.end(); it++)
  203. {
  204. if (pHeadItem->subDirFirstItem)
  205. pNextItem = m_BurnItem.AddFile2SiblingItem(pNextItem, *it);
  206. else
  207. pNextItem = m_BurnItem.AddFile2Path(pHeadItem, *it);
  208. if (!pNextItem) break;
  209. }
  210. }
  211. else
  212. {
  213. for (vector<TString>::iterator it = vtfiles.begin(); it != vtfiles.end(); it++)
  214. {
  215. pHeadItem = m_BurnItem.AddFile2SiblingItem(pHeadItem, *it);
  216. if (!pHeadItem) break;
  217. }
  218. }
  219. }
  220. }
  221. void CNeroImpl::AddFolder2Disc(IN CONST TString& folder, NERO_ISO_ITEM* pFolderItem)
  222. {
  223. TString path = folder;
  224. if (path.size() > 0 && _T('\\') != path[path.size() - 1])
  225. path.append(_T("\\"));
  226. TString file = _T("*");
  227. TString s = path + file;
  228. WIN32_FIND_DATA fileinfo = { 0 };
  229. HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
  230. NERO_ISO_ITEM* pNextItem = NULL;
  231. if (NULL != handle && INVALID_HANDLE_VALUE != handle)
  232. {
  233. do
  234. {
  235. // 检查是否超过最大数;
  236. //if (checklimit()) break;
  237. // '.'和 '..'的系统文件去除;
  238. if (_T('.') != fileinfo.cFileName[0])
  239. {
  240. if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY) // 目录;
  241. {
  242. pNextItem = m_BurnItem.FindPathInSibling(pFolderItem->subDirFirstItem, TString(fileinfo.cFileName));
  243. if (pNextItem == NULL)
  244. AddFolder2Disc(path + fileinfo.cFileName, m_BurnItem.AddPath2Path(pFolderItem, fileinfo.cFileName));
  245. else
  246. AddFolder2Disc(path + fileinfo.cFileName, pNextItem);
  247. }
  248. else
  249. {
  250. //if (!checklimit())
  251. if (pFolderItem->subDirFirstItem == NULL)
  252. pNextItem = m_BurnItem.AddFile2Path(pFolderItem, path + fileinfo.cFileName);
  253. else
  254. {
  255. if (pNextItem == NULL)
  256. pNextItem = m_BurnItem.FindLastItemInSibling(pFolderItem->subDirFirstItem);
  257. pNextItem = m_BurnItem.AddFile2SiblingItem(pNextItem, path + fileinfo.cFileName);
  258. }
  259. }
  260. }
  261. } while (FindNextFile(handle, &fileinfo));
  262. FindClose(handle);
  263. }
  264. }
  265. void CNeroImpl::AddFolder2Disc(TString strFatherNode, TString strFolder)
  266. {
  267. m_BurnItem.InitVituralItem();
  268. NERO_ISO_ITEM* pFolderItem = NULL;
  269. if (strFatherNode.size() == 0)
  270. {//所有文件,都加到根目录下;
  271. strFatherNode = strFolder;
  272. if (strFolder[strFolder.size() - 1] == _T('\\'))
  273. strFatherNode = strFolder.substr(0, strFolder.size() - 1);
  274. strFatherNode = strFatherNode.substr(strFatherNode.find_last_of('\\') + 1);
  275. }
  276. pFolderItem = m_BurnItem.FindPathItem(strFatherNode);
  277. if (!pFolderItem)
  278. {// 新添根结点;
  279. pFolderItem = m_BurnItem.AddPath(strFatherNode);
  280. }
  281. if (pFolderItem == NULL)
  282. return;
  283. pFolderItem->isDirectory = TRUE;
  284. AddFolder2Disc(strFolder, pFolderItem);
  285. }
  286. bool CNeroImpl::BurnMedia(int nIndex, TString strArtist, TString strTitle)
  287. {
  288. // 使用第一个设备来刻录;;
  289. NERO_SCSI_DEVICE_INFO* nsdiDevice = &m_pNeroDeviceInfos->nsdisDevInfos[0];
  290. // 打开设备;
  291. NERO_DEVICEHANDLE hDevice = NeroOpenDevice(nsdiDevice);
  292. if (!hDevice)
  293. {
  294. AfxMessageBox(_T("刻录设备不能打开, 请与系统管理员联系!"), MB_ICONSTOP);
  295. return false;
  296. }
  297. // 读取CD或DVD媒体信息;
  298. NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(hDevice, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC);
  299. if (pNeroCDInfo == NULL)
  300. {
  301. NeroCloseDevice(hDevice);
  302. AfxMessageBox(_T("获取光盘失败, 请与系统管理员联系!"), MB_ICONSTOP);
  303. return false;
  304. }
  305. // 光盘不可写;
  306. if (!pNeroCDInfo->ncdiIsWriteable)
  307. {
  308. NeroCloseDevice(hDevice);
  309. AfxMessageBox(_T("光盘不可写, 请更换新的光盘!"), MB_ICONSTOP);
  310. return false;
  311. }
  312. #if 0
  313. // 光盘文件系统格式(但是,好像没有用, 估计是SDK版本太老);
  314. // pNeroCDInfo->ncdiTrackInfos[0].ntiFSType; // NTFST_UDF DVD格式刻录; NTFST_CDRFS CD格式刻录;
  315. if (m_bDvd && pNeroCDInfo->ncdiTrackInfos[0].ntiFSType == NTFST_CDRFS)
  316. {
  317. AfxMessageBox(_T("所选DVD格式刻录,但光盘文件系统是CD格式,请更换DVD文件系统(UDF或新)的光盘!"), MB_ICONSTOP);
  318. NeroWorkError = true;
  319. return;
  320. }
  321. if (!m_bDvd && pNeroCDInfo->ncdiTrackInfos[0].ntiFSType == NTFST_UDF)
  322. {
  323. AfxMessageBox(_T("所选DVD格式刻录,但光盘文件系统是CD格式,请更换DVD文件系统(UDF或新)的光盘!"), MB_ICONSTOP);
  324. NeroWorkError = true;
  325. return;
  326. }
  327. #endif
  328. // 设置写CD参数 ;
  329. NERO_WRITE_CD writeCD;
  330. memset(&writeCD, 0, sizeof(writeCD));
  331. writeCD.nwcdpCDStamp = NULL;
  332. writeCD.nwcdArtist = NULL;
  333. writeCD.nwcdTitle = NULL;
  334. writeCD.nwcdCDExtra = FALSE;
  335. writeCD.nwcdNumTracks = 0;
  336. // writeCD.nwcdMediaType = m_bDvd ? MEDIA_DVD_ANY : MEDIA_CD; // 这里不是按光盘的媒体类型来赋值;
  337. writeCD.nwcdMediaType = pNeroCDInfo->ncdiMediaType;
  338. if (true)
  339. {// 追加方式刻录;
  340. NERO_IMPORT_DATA_TRACK_INFO nidtInfo;
  341. NERO_IMPORT_DATA_TRACK_RESULT nidtResult;
  342. // Prepare the struct.
  343. //TString csUserMsg = "";
  344. memset(&nidtInfo, 0, sizeof(nidtInfo));
  345. nidtInfo.nidtiSize = sizeof(nidtInfo);
  346. void* pCDStamp = NULL;
  347. NERO_ISO_ITEM* pniiItem = NULL;
  348. pniiItem = NeroImportDataTrack(hDevice, pNeroCDInfo->ncdiNumTracks - 1, &pCDStamp, &nidtInfo, 0, &nidtResult, NULL);
  349. // If there is a volume name after import, print it out.
  350. if (nidtInfo.nidtipVolumeName != NULL)
  351. {
  352. //csUserMsg.Format("Imported volume name: %s", nidtInfo.nidtipVolumeName);
  353. //AppendString(csUserMsg);
  354. NeroFreeMem(nidtInfo.nidtipVolumeName);
  355. }
  356. // If there was an error during import, let the user know about it.
  357. if ((nidtResult != NIDTR_NO_ERROR) || (pniiItem == NULL))
  358. {
  359. static LPCSTR errors[] = { "an unknown error","a generic error","a drive error","a read error","a filesystem error","an invalid track number" };
  360. if (nidtResult > NIDTR_INVALID_TRACKNUMBER)
  361. nidtResult = NIDTR_NO_ERROR;
  362. // 释放资源;
  363. if (pCDStamp != NULL)
  364. NeroFreeCDStamp(pCDStamp), pCDStamp = NULL;
  365. NeroFreeMem(pNeroCDInfo);
  366. NeroCloseDevice(hDevice);
  367. m_BurnItem.RemoveAllItem();
  368. return false;
  369. //csUserMsg.Format("There was %s while importing the track!", errors[nidtResult]);
  370. //AppendString(csUserMsg);
  371. }
  372. else if (m_BurnItem.GetHeadItem() != NULL)
  373. {
  374. if (MergeIsoTracks(&m_BurnItem.GetVirtualItem()->subDirFirstItem, pniiItem)) // Merge the new track with the existing one.
  375. writeCD.nwcdpCDStamp = pCDStamp;
  376. else
  377. {
  378. //AppendString("There was an error while merging tracks!");
  379. if (pCDStamp != NULL)
  380. NeroFreeCDStamp(pCDStamp), pCDStamp = NULL;
  381. }
  382. }
  383. }
  384. #ifdef UNICODE
  385. writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_BurnItem.GetHeadItem(),
  386. convert("UCS-2LE", "gb2312", (const char*)strTitle.c_str(), strTitle.size() * sizeof(TCHAR)).c_str(),
  387. NCITEF_USE_JOLIET | NCITEF_CREATE_ISO_FS);
  388. #else
  389. writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_BurnItem.GetHeadItem(), strTitle.c_str(), NCITEF_USE_JOLIET | NCITEF_CREATE_ISO_FS);
  390. #endif
  391. // 以追回的方式刻录(NBF_CLOSE_SESSION) : 使用MEDIA_DVD_ANY 或 MEDIA_CD时, NERO_CD_FORMAT固定为NERO_ISO_AUDIO_MEDIA;
  392. int iRes = NeroBurn(hDevice, NERO_ISO_AUDIO_MEDIA, &writeCD, NBF_WRITE | NBF_CLOSE_SESSION, 0/*Maximum*/, &m_NeroProgress);
  393. // 释放媒体资源;
  394. NeroFreeMem(pNeroCDInfo);
  395. // free memory that was allocated for the track
  396. if (writeCD.nwcdIsoTrack != NULL)
  397. NeroFreeIsoTrack(writeCD.nwcdIsoTrack);
  398. NeroCloseDevice(hDevice);
  399. m_BurnItem.RemoveAllItem();
  400. // Free the NERO_WRITE_CD struct too
  401. if (writeCD.nwcdpCDStamp != NULL)
  402. NeroFreeCDStamp(writeCD.nwcdpCDStamp), writeCD.nwcdpCDStamp = NULL;
  403. char* pszLog = NeroGetErrorLog();
  404. switch (iRes)
  405. {
  406. case NEROAPI_BURN_OK:
  407. AfxMessageBox(_T("刻录成功!"), MB_ICONINFORMATION);
  408. break;
  409. case NEROAPI_BURN_UNKNOWN_CD_FORMAT:
  410. AfxMessageBox(_T("刻录失败:无效刻录盘格式!"), MB_ICONSTOP);
  411. break;
  412. case NEROAPI_BURN_INVALID_DRIVE:
  413. AfxMessageBox(_T("刻录失败:驱动器无效!"), MB_ICONSTOP);
  414. break;
  415. case NEROAPI_BURN_FAILED:
  416. AfxMessageBox(_T("刻录失败!"), MB_ICONSTOP);
  417. break;
  418. case NEROAPI_BURN_FUNCTION_NOT_ALLOWED:
  419. case NEROAPI_BURN_DRIVE_NOT_ALLOWED:
  420. AfxMessageBox(_T("刻录失败:刻录驱动未安装正确!"), MB_ICONSTOP);
  421. break;
  422. default:
  423. AfxMessageBox(_T("刻录失败:未知错误!"), MB_ICONSTOP);
  424. break;
  425. }
  426. NeroFreeMem(pszLog);
  427. return true;
  428. }
  429. void CNeroImpl::EraseMedia(int nIndex)
  430. {
  431. ASSERT(nIndex);
  432. if (nIndex > m_pNeroDeviceInfos->nsdisNumDevInfos)
  433. return;
  434. NERO_SCSI_DEVICE_INFO *pDevInfo = &m_pNeroDeviceInfos->nsdisDevInfos[nIndex];
  435. NERO_DEVICEHANDLE hNeroDevice = NeroOpenDevice(pDevInfo);
  436. //NEROAPI_CDRW_ERASE_MODE mode = bEraseEntire ? NEROAPI_ERASE_ENTIRE : NEROAPI_ERASE_QUICK;
  437. NEROAPI_CDRW_ERASE_MODE mode = NEROAPI_ERASE_ENTIRE;
  438. int time = NeroGetCDRWErasingTime(hNeroDevice, mode);
  439. if (time == -1)
  440. m_strLastError = _T("No CD inserted");
  441. else if (time == -2)
  442. m_strLastError = _T("This CD recorder doesn't support CDRW");
  443. else if (time == -3)
  444. m_strLastError = _T("This media is not rewritable");
  445. int err = NeroEraseCDRW(hNeroDevice, mode);
  446. if (err)
  447. m_strLastError = _T("Error erasing the CDRW");
  448. NeroCloseDevice(hNeroDevice);
  449. }
  450. bool CNeroImpl::SetWriteSpeed(ULONG nIndex)
  451. {
  452. return false;
  453. }
  454. void CNeroImpl::NeroCallback(void * pDailog, IdleCallback pIdleCallback, UserDialog pUserDialog, ProgressCallback pProgressCallback, ProgressCallback pSubTaskProgressCallback, AbortedCallback pAbortedCallback, AddLogLine pAddLogLine, SetPhaseCallback pSetPhaseCallback, DisableAbortCallback pDisableAbortCallback, SetMajorPhaseCallback pSetMajorPhaseCallback, WriteIOCallback pWriteIOCallback, ReadIOCallback pReadIOCallback, EOFCallback pEOFCallback, ErrorCallback pErrorCallback)
  455. {
  456. CNeroImpl::m_pDailog = (CDialog*)pDailog;
  457. CNeroImpl::m_pIdelCallback = pIdleCallback;
  458. CNeroImpl::m_pUserDialog = pUserDialog;
  459. CNeroImpl::m_pProgressCallback = pProgressCallback;
  460. CNeroImpl::m_pSubTaskProgressCallback = pSubTaskProgressCallback;
  461. CNeroImpl::m_pAbortedCallback = pAbortedCallback;
  462. CNeroImpl::m_pAddLogLine = pAddLogLine;
  463. CNeroImpl::m_pSetPhaseCallback = pSetPhaseCallback;
  464. CNeroImpl::m_pDisableAbortCallback = pDisableAbortCallback;
  465. CNeroImpl::m_pSetMajorPhaseCallback = pSetMajorPhaseCallback;
  466. CNeroImpl::m_pWriteIOCallback = pWriteIOCallback;
  467. CNeroImpl::m_pReadIOCallback = pReadIOCallback;
  468. CNeroImpl::m_pEOFCallback = pEOFCallback;
  469. CNeroImpl::m_pErrorCallback = pErrorCallback;
  470. }
  471. inline LPCSTR GetFilename(const NERO_ISO_ITEM* pItem)
  472. {
  473. return (pItem->longFileName != NULL) ? pItem->longFileName : pItem->fileName;
  474. }
  475. // The following function performs a merge operation between two iso item trees.
  476. // The second tree is added onto the first one and the extra items are deleted.
  477. // As we do not allow to add directories in our file list we do not make recursive
  478. // calls of this method.
  479. BOOL CNeroImpl::MergeIsoTracks(NERO_ISO_ITEM** ppniiTarget, NERO_ISO_ITEM* pniiToAdd)
  480. {
  481. BOOL bResult = ((ppniiTarget != NULL) && (*ppniiTarget != NULL) && (pniiToAdd != NULL));
  482. // Two loops. Outer loops the first tree, the inner loops the second tree.
  483. for (; bResult && (*ppniiTarget != NULL); ppniiTarget = &(*ppniiTarget)->nextItem)
  484. {
  485. for (NERO_ISO_ITEM** ppniiToAddLocal = &pniiToAdd; *ppniiToAddLocal != NULL; )
  486. {
  487. // Compare entry names...
  488. if (0 == _stricmp(GetFilename(*ppniiTarget), GetFilename(*ppniiToAddLocal)))
  489. {
  490. // If there is a file name conflict between iso items that belong to imported sessions
  491. // always replace the old files in terms of modification times.
  492. time_t timeTarget = mktime(&(*ppniiTarget)->entryTime);
  493. if (timeTarget == (time_t)-1)
  494. {
  495. HANDLE hFile = NULL; // handle to file
  496. FILETIME ftCreationTime; // creation time
  497. FILETIME ftLastAccessTime; // last access time
  498. FILETIME ftLastWriteTime; // last write time
  499. hFile = CreateFileA((*ppniiTarget)->longSourceFilePath, // open the file to get handle
  500. GENERIC_READ, // open for reading
  501. FILE_SHARE_READ, // share for reading
  502. NULL, // no security
  503. OPEN_EXISTING, // existing file only
  504. FILE_ATTRIBUTE_NORMAL, // normal file
  505. NULL); // no attr. template
  506. if (hFile == INVALID_HANDLE_VALUE)
  507. {
  508. CStringA csMsg;
  509. csMsg.Format("Could not open file: %s.", (*ppniiTarget)->longSourceFilePath);
  510. //AppendString(csMsg); // show error
  511. }
  512. else if (GetFileTime(hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
  513. timeTarget = CTime(ftLastWriteTime).GetTime();
  514. if (hFile != INVALID_HANDLE_VALUE)
  515. CloseHandle(hFile), hFile = NULL;
  516. }
  517. time_t timeToAdd = mktime(&(*ppniiToAddLocal)->entryTime);
  518. // If we have to replace one item, we will now switch places of items in the first and second tree.
  519. // Since one of the items has to be deleted eventually, this operation will
  520. // essentially keep the item from the second tree and delete the item from the first tree.
  521. if (timeTarget < timeToAdd)
  522. {
  523. NERO_ISO_ITEM* pniiTmpItem = *ppniiToAddLocal;
  524. *ppniiToAddLocal = *ppniiTarget;
  525. *ppniiTarget = pniiTmpItem;
  526. pniiTmpItem = (*ppniiToAddLocal)->nextItem;
  527. (*ppniiToAddLocal)->nextItem = (*ppniiTarget)->nextItem;
  528. (*ppniiTarget)->nextItem = pniiTmpItem;
  529. }
  530. // Remove the item from the second tree.
  531. NERO_ISO_ITEM* pniiTmpItem = *ppniiToAddLocal;
  532. *ppniiToAddLocal = pniiTmpItem->nextItem;
  533. pniiTmpItem->nextItem = NULL;
  534. DeleteIsoItemTree(pniiTmpItem);
  535. }
  536. else // No match, advance to the next item.
  537. ppniiToAddLocal = &(*ppniiToAddLocal)->nextItem;
  538. }
  539. }
  540. // Attach whatever is left of the new tree to the main tree.
  541. *ppniiTarget = pniiToAdd;
  542. // Returning true means, everything is fine, continue.
  543. return bResult;
  544. }
  545. // This function deletes the iso tree recursively.
  546. void CNeroImpl::DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem)
  547. {
  548. // First free our own long filename strings, then free the whole tree.
  549. FreeOurOwnResources(pniiItem);
  550. NeroFreeIsoItemTree(pniiItem);
  551. }
  552. void CNeroImpl::FreeOurOwnResources(NERO_ISO_ITEM* pniiItem)
  553. {
  554. // Step through the tree until the ISO item tree pointer becomes NULL
  555. while (pniiItem != NULL)
  556. {
  557. NERO_ISO_ITEM* pniiNextItem = pniiItem->nextItem;
  558. // We have encountered another ISO item tree; recurse another level.
  559. if (pniiItem->isDirectory)
  560. FreeOurOwnResources(pniiItem->subDirFirstItem);
  561. if (!pniiItem->isReference)
  562. {
  563. if (pniiItem->longFileName != NULL)
  564. free((void*)pniiItem->longFileName), pniiItem->longFileName = NULL;
  565. if (pniiItem->longSourceFilePath != NULL)
  566. free((void*)pniiItem->longSourceFilePath), pniiItem->longSourceFilePath = NULL;
  567. }
  568. pniiItem = pniiNextItem;
  569. }
  570. }