BurnCDDlg.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. // BurnCDDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "BurnCD.h"
  5. #include "BurnCDDlg.h"
  6. #include "DiscMaster.h"
  7. #include "FileObject.h"
  8. #include "DirObject.h"
  9. #include "DiscFormatData.h"
  10. #include "DiscRecorder.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #endif
  14. #define CD_MEDIA 0
  15. #define DVD_MEDIA 1
  16. #define DL_DVD_MEDIA 2
  17. #define WM_BURN_STATUS_MESSAGE WM_APP+300
  18. #define WM_BURN_FINISHED WM_APP+301
  19. #define CLIENT_NAME _T("BurnCD")
  20. // CBurnCDDlg dialog
  21. CBurnCDDlg::CBurnCDDlg(CWnd* pParent /*=NULL*/)
  22. : CDialog(CBurnCDDlg::IDD, pParent)
  23. , m_closeMedia(TRUE)
  24. , m_cancelBurn(false)
  25. , m_selectedMediaType(-1)
  26. , m_isBurning(false)
  27. , m_ejectWhenFinished(TRUE)
  28. {
  29. m_volumeLabel = CTime::GetCurrentTime().Format(_T("%Y_%m_%d"));
  30. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  31. }
  32. void CBurnCDDlg::DoDataExchange(CDataExchange* pDX)
  33. {
  34. CDialog::DoDataExchange(pDX);
  35. DDX_Control(pDX, IDC_DEVICE_COMBO, m_deviceComboBox);
  36. DDX_Control(pDX, IDC_BURN_FILE_LIST, m_fileListbox);
  37. DDX_Control(pDX, IDC_PROGRESS_TEXT, m_progressText);
  38. DDX_Control(pDX, IDC_ESTIMATED_TIME, m_estimatedTime);
  39. DDX_Control(pDX, IDC_TIME_LEFT, m_timeLeft);
  40. DDX_Control(pDX, IDC_PROGRESS, m_progressCtrl);
  41. DDX_Control(pDX, IDC_BUFFER_TEXT, m_bufferText);
  42. DDX_Control(pDX, IDC_BUFFER_PROG, m_bufferCtrl);
  43. DDX_Control(pDX, IDC_SUPPORTED_MEDIA_TYPES, m_supportedMediaTypes);
  44. DDX_Control(pDX, IDC_CAPACITY, m_capacityProgress);
  45. DDX_Control(pDX, IDC_MAX_TEXT, m_maxText);
  46. DDX_Control(pDX, IDC_MEDIA_TYPE_COMBO, m_mediaTypeCombo);
  47. DDX_Text(pDX, IDC_VOLUME, m_volumeLabel);
  48. DDX_Check(pDX, IDC_CLOSE_MEDIA_CHK, m_closeMedia);
  49. DDX_Check(pDX, IDC_EJECT_WHEN_FINISHED, m_ejectWhenFinished);
  50. }
  51. BEGIN_MESSAGE_MAP(CBurnCDDlg, CDialog)
  52. ON_CBN_SELCHANGE(IDC_DEVICE_COMBO, &CBurnCDDlg::OnCbnSelchangeDeviceCombo)
  53. ON_LBN_SELCHANGE(IDC_BURN_FILE_LIST, &CBurnCDDlg::OnLbnSelchangeBurnFileList)
  54. ON_BN_CLICKED(IDC_ADD_FILES_BUTTON, &CBurnCDDlg::OnBnClickedAddFilesButton)
  55. ON_BN_CLICKED(IDC_ADD_FOLDER_BUTTON, &CBurnCDDlg::OnBnClickedAddFolderButton)
  56. ON_WM_DESTROY()
  57. ON_BN_CLICKED(IDC_BURN_BUTTON, &CBurnCDDlg::OnBnClickedBurnButton)
  58. ON_MESSAGE(WM_IMAPI_UPDATE, OnImapiUpdate)
  59. ON_MESSAGE(WM_BURN_STATUS_MESSAGE, OnBurnStatusMessage)
  60. ON_MESSAGE(WM_BURN_FINISHED, OnBurnFinished)
  61. ON_CBN_SELCHANGE(IDC_MEDIA_TYPE_COMBO, &CBurnCDDlg::OnCbnSelchangeMediaTypeCombo)
  62. ON_BN_CLICKED(IDC_REMOVE_FILES_BUTTON, &CBurnCDDlg::OnBnClickedRemoveFilesButton)
  63. //}}AFX_MSG_MAP
  64. END_MESSAGE_MAP()
  65. // CBurnCDDlg message handlers
  66. BOOL CBurnCDDlg::OnInitDialog()
  67. {
  68. CDialog::OnInitDialog();
  69. m_progressText.SetWindowText(_T(""));
  70. m_bufferText.SetWindowText(_T(""));
  71. m_supportedMediaTypes.SetWindowText(_T(""));
  72. m_maxText.SetWindowText(_T(""));
  73. m_capacityProgress.SetRange(0,100);
  74. AddRecordersToComboBox();
  75. OnLbnSelchangeBurnFileList();
  76. EnableBurnButton();
  77. // Set the icon for this dialog. The framework does this automatically
  78. // when the application's main window is not a dialog
  79. SetIcon(m_hIcon, TRUE); // Set big icon
  80. SetIcon(m_hIcon, FALSE); // Set small icon
  81. return TRUE; // return TRUE unless you set the focus to a control
  82. }
  83. void CBurnCDDlg::AddRecordersToComboBox()
  84. {
  85. CDiscMaster discMaster;
  86. //
  87. // Cleanup old data on combobox
  88. //
  89. int itemCount = m_deviceComboBox.GetCount();
  90. for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
  91. {
  92. delete (CDiscRecorder*)m_deviceComboBox.GetItemDataPtr(itemIndex);
  93. }
  94. m_deviceComboBox.ResetContent();
  95. if (!discMaster.Initialize())
  96. {
  97. AfxMessageBox(discMaster.GetErrorMessage(), MB_OK|MB_ICONERROR);
  98. EndDialog(IDOK);
  99. return;
  100. }
  101. //
  102. // Add Devices to ComboBox
  103. //
  104. long totalDevices = discMaster.GetTotalDevices();
  105. if (totalDevices == 0 && FAILED(discMaster.GetHresult()))
  106. {
  107. AfxMessageBox(discMaster.GetErrorMessage(), MB_OK|MB_ICONERROR);
  108. }
  109. for (long deviceIndex = 0; deviceIndex < totalDevices; deviceIndex++)
  110. {
  111. CString recorderUniqueID = discMaster.GetDeviceUniqueID(deviceIndex);
  112. if (recorderUniqueID.IsEmpty())
  113. {
  114. CString errorMessage(discMaster.GetErrorMessage());
  115. if (!errorMessage.IsEmpty())
  116. {
  117. AfxMessageBox(errorMessage, MB_OK|MB_ICONERROR);
  118. continue;
  119. }
  120. }
  121. //
  122. // Create an IDiscRecorder2
  123. //
  124. CDiscRecorder* pDiscRecorder = new CDiscRecorder();
  125. ASSERT(pDiscRecorder != NULL);
  126. if (pDiscRecorder == NULL)
  127. continue;
  128. if (!pDiscRecorder->Initialize(recorderUniqueID))
  129. {
  130. if (totalDevices == 1 && FAILED(pDiscRecorder->GetHresult()))
  131. {
  132. CString errorMessage;
  133. errorMessage.Format(_T("Failed to initialize recorder - Error:0x%08x\n\nRecorder Unique ID:%s"),
  134. pDiscRecorder->GetHresult(), (LPCTSTR)recorderUniqueID);
  135. AfxMessageBox(errorMessage, MB_OK|MB_ICONERROR);
  136. }
  137. delete pDiscRecorder;
  138. continue;
  139. }
  140. //
  141. // Get the volume path(s). usually just 1
  142. //
  143. CString volumeList;
  144. ULONG totalVolumePaths = pDiscRecorder->GetTotalVolumePaths();
  145. for (ULONG volIndex = 0; volIndex < totalVolumePaths; volIndex++)
  146. {
  147. if (volIndex)
  148. volumeList += _T(",");
  149. volumeList += pDiscRecorder->GetVolumePath(volIndex);
  150. }
  151. //
  152. // Add Drive to combo and IDiscRecorder as data
  153. //
  154. CString productId = pDiscRecorder->GetProductID();
  155. CString strName;
  156. strName.Format(_T("%s [%s]"), (LPCTSTR)volumeList, (LPCTSTR)productId);
  157. int comboBoxIndex = m_deviceComboBox.AddString(strName);
  158. m_deviceComboBox.SetItemDataPtr(comboBoxIndex, pDiscRecorder);
  159. #ifdef _DEBUG
  160. CDiscFormatData discFormatData;
  161. if (discFormatData.Initialize(pDiscRecorder, CLIENT_NAME))
  162. {
  163. // 获取当前媒体的大小;
  164. LONG ulCapity = 0;
  165. discFormatData.GetFreeSectorsOnMedia(ulCapity);
  166. //
  167. // Get the media type currently in the recording device
  168. //
  169. IMAPI_MEDIA_PHYSICAL_TYPE mediaType = IMAPI_MEDIA_TYPE_UNKNOWN;
  170. discFormatData.GetInterface()->get_CurrentPhysicalMediaType(&mediaType);
  171. // 获取光盘支持的写入速度列表;
  172. }
  173. #endif
  174. }
  175. if (totalDevices > 0)
  176. {
  177. m_deviceComboBox.SetCurSel(0);
  178. OnCbnSelchangeDeviceCombo();
  179. }
  180. }
  181. //
  182. // CBurnCDDlg::OnCbnSelchangeDeviceCombo
  183. //
  184. // Selected a New Device
  185. //
  186. void CBurnCDDlg::OnCbnSelchangeDeviceCombo()
  187. {
  188. m_isCdromSupported = false;
  189. m_isDvdSupported = false;
  190. m_isDualLayerDvdSupported = false;
  191. m_mediaTypeCombo.ResetContent();
  192. int selectedIndex = m_deviceComboBox.GetCurSel();
  193. ASSERT(selectedIndex >= 0);
  194. if (selectedIndex < 0)
  195. {
  196. return;
  197. }
  198. CDiscRecorder* discRecorder =
  199. (CDiscRecorder*)m_deviceComboBox.GetItemDataPtr(selectedIndex);
  200. if (discRecorder != NULL)
  201. {
  202. CDiscFormatData discFormatData;
  203. if (!discFormatData.Initialize(discRecorder, CLIENT_NAME))
  204. {
  205. return;
  206. }
  207. //
  208. // Display Supported Media Types
  209. //
  210. CString supportedMediaTypes;
  211. ULONG totalMediaTypes = discFormatData.GetTotalSupportedMediaTypes();
  212. for (ULONG volIndex = 0; volIndex < totalMediaTypes; volIndex++)
  213. {
  214. int mediaType = discFormatData.GetSupportedMediaType(volIndex);
  215. if (volIndex > 0)
  216. supportedMediaTypes += _T(", ");
  217. supportedMediaTypes += GetMediaTypeString(mediaType);
  218. }
  219. m_supportedMediaTypes.SetWindowText(supportedMediaTypes);
  220. //
  221. // Add Media Selection
  222. //
  223. if (m_isCdromSupported)
  224. {
  225. int stringIndex = m_mediaTypeCombo.AddString(_T("700MB CD Media"));
  226. m_mediaTypeCombo.SetItemData(stringIndex, CD_MEDIA);
  227. }
  228. if (m_isDvdSupported)
  229. {
  230. int stringIndex = m_mediaTypeCombo.AddString(_T("4.7GB DVD Media"));
  231. m_mediaTypeCombo.SetItemData(stringIndex, DVD_MEDIA);
  232. }
  233. if (m_isDualLayerDvdSupported)
  234. {
  235. int stringIndex = m_mediaTypeCombo.AddString(_T("8.5GB Dual-Layer DVD"));
  236. m_mediaTypeCombo.SetItemData(stringIndex, DL_DVD_MEDIA);
  237. }
  238. m_mediaTypeCombo.SetCurSel(0);
  239. OnCbnSelchangeMediaTypeCombo();
  240. }
  241. }
  242. CString CBurnCDDlg::GetMediaTypeString(int mediaType)
  243. {
  244. switch (mediaType)
  245. {
  246. case IMAPI_MEDIA_TYPE_UNKNOWN:
  247. default:
  248. return _T("Unknown Media Type");
  249. case IMAPI_MEDIA_TYPE_CDROM:
  250. m_isCdromSupported = true;
  251. return _T("CD-ROM or CD-R/RW media");
  252. case IMAPI_MEDIA_TYPE_CDR:
  253. m_isCdromSupported = true;
  254. return _T("CD-R");
  255. case IMAPI_MEDIA_TYPE_CDRW:
  256. m_isCdromSupported = true;
  257. return _T("CD-RW");
  258. case IMAPI_MEDIA_TYPE_DVDROM:
  259. m_isDvdSupported = true;
  260. return _T("DVD ROM");
  261. case IMAPI_MEDIA_TYPE_DVDRAM:
  262. m_isDvdSupported = true;
  263. return _T("DVD-RAM");
  264. case IMAPI_MEDIA_TYPE_DVDPLUSR:
  265. m_isDvdSupported = true;
  266. return _T("DVD+R");
  267. case IMAPI_MEDIA_TYPE_DVDPLUSRW:
  268. m_isDvdSupported = true;
  269. return _T("DVD+RW");
  270. case IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER:
  271. m_isDualLayerDvdSupported = true;
  272. return _T("DVD+R Dual Layer");
  273. case IMAPI_MEDIA_TYPE_DVDDASHR:
  274. m_isDvdSupported = true;
  275. return _T("DVD-R");
  276. case IMAPI_MEDIA_TYPE_DVDDASHRW:
  277. m_isDvdSupported = true;
  278. return _T("DVD-RW");
  279. case IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER:
  280. m_isDualLayerDvdSupported = true;
  281. return _T("DVD-R Dual Layer");
  282. case IMAPI_MEDIA_TYPE_DISK:
  283. return _T("random-access writes");
  284. case IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER:
  285. m_isDualLayerDvdSupported = true;
  286. return _T("DVD+RW DL");
  287. case IMAPI_MEDIA_TYPE_HDDVDROM:
  288. return _T("HD DVD-ROM");
  289. case IMAPI_MEDIA_TYPE_HDDVDR:
  290. return _T("HD DVD-R");
  291. case IMAPI_MEDIA_TYPE_HDDVDRAM:
  292. return _T("HD DVD-RAM");
  293. case IMAPI_MEDIA_TYPE_BDROM:
  294. return _T("Blu-ray DVD (BD-ROM)");
  295. case IMAPI_MEDIA_TYPE_BDR:
  296. return _T("Blu-ray media");
  297. case IMAPI_MEDIA_TYPE_BDRE:
  298. return _T("Blu-ray Rewritable media");
  299. }
  300. }
  301. void CBurnCDDlg::OnLbnSelchangeBurnFileList()
  302. {
  303. GetDlgItem(IDC_REMOVE_FILES_BUTTON)->EnableWindow(m_fileListbox.GetCurSel()!=-1);
  304. }
  305. void CBurnCDDlg::OnBnClickedAddFilesButton()
  306. {
  307. CFileDialog fileDialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, _T("All Files (*.*)|*.*||"), NULL, 0);
  308. if (fileDialog.DoModal() == IDOK)
  309. {
  310. CFileObject* pFileObject = new CFileObject(fileDialog.GetPathName());
  311. int addIndex = m_fileListbox.AddString(pFileObject->GetName());
  312. m_fileListbox.SetItemDataPtr(addIndex, pFileObject);
  313. UpdateCapacity();
  314. EnableBurnButton();
  315. }
  316. }
  317. void CBurnCDDlg::OnBnClickedAddFolderButton()
  318. {
  319. BROWSEINFO bi = {0};
  320. bi.hwndOwner = m_hWnd;
  321. bi.ulFlags = BIF_RETURNONLYFSDIRS;//|BIF_USENEWUI;
  322. LPITEMIDLIST lpidl = SHBrowseForFolder(&bi);
  323. if (!lpidl)
  324. return;
  325. TCHAR selectedPath[_MAX_PATH] = {0};
  326. if (SHGetPathFromIDList(lpidl, selectedPath))
  327. {
  328. CDirObject* pDirObject = new CDirObject(selectedPath);
  329. int addIndex = m_fileListbox.AddString(pDirObject->GetName());
  330. m_fileListbox.SetItemDataPtr(addIndex, pDirObject);
  331. UpdateCapacity();
  332. EnableBurnButton();
  333. }
  334. }
  335. void CBurnCDDlg::OnDestroy()
  336. {
  337. int itemCount = m_fileListbox.GetCount();
  338. for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
  339. {
  340. delete (CBaseObject*)m_fileListbox.GetItemDataPtr(itemIndex);
  341. }
  342. itemCount = m_deviceComboBox.GetCount();
  343. for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
  344. {
  345. delete (CDiscRecorder*)m_deviceComboBox.GetItemDataPtr(itemIndex);
  346. }
  347. CDialog::OnDestroy();
  348. }
  349. void CBurnCDDlg::OnBnClickedBurnButton()
  350. {
  351. if (m_isBurning)
  352. {
  353. SetCancelBurning(true);
  354. }
  355. else
  356. {
  357. SetCancelBurning(false);
  358. m_isBurning = true;
  359. UpdateData();
  360. EnableUI(false);
  361. AfxBeginThread(BurnThread, this, THREAD_PRIORITY_NORMAL);
  362. }
  363. }
  364. UINT CBurnCDDlg::BurnThread(LPVOID pParam)
  365. {
  366. CBurnCDDlg* pThis = (CBurnCDDlg*)pParam;
  367. //
  368. // Get the selected recording device from the combobox
  369. //
  370. int selectedIndex = pThis->m_deviceComboBox.GetCurSel();
  371. ASSERT(selectedIndex >= 0);
  372. if (selectedIndex < 0)
  373. {
  374. pThis->SendMessage(WM_BURN_FINISHED, 0, (LPARAM)_T("Error: No Device Selected"));
  375. return 0;
  376. }
  377. CDiscRecorder* pOrigDiscRecorder =
  378. (CDiscRecorder*)pThis->m_deviceComboBox.GetItemDataPtr(selectedIndex);
  379. if (pOrigDiscRecorder == NULL)
  380. {
  381. //
  382. // This should never happen
  383. //
  384. pThis->SendMessage(WM_BURN_FINISHED, 0, (LPARAM)_T("Error: No Data for selected device"));
  385. return 0;
  386. }
  387. //
  388. // Did user cancel?
  389. //
  390. if (pThis->GetCancelBurning())
  391. {
  392. pThis->SendMessage(WM_BURN_FINISHED, 0, (LPARAM)_T("User Canceled!"));
  393. return 0;
  394. }
  395. pThis->SendMessage(WM_BURN_STATUS_MESSAGE, 0, (LPARAM)_T("Initializing Disc Recorder..."));
  396. //
  397. // Create another disc recorder because we're in a different thread
  398. //
  399. CDiscRecorder discRecorder;
  400. CString errorMessage;
  401. if (discRecorder.Initialize(pOrigDiscRecorder->GetUniqueId()))
  402. {
  403. //
  404. // 获得对设备的独占访问权限;
  405. //
  406. if (discRecorder.AcquireExclusiveAccess(true, CLIENT_NAME))
  407. {
  408. CDiscFormatData discFormatData;
  409. if (discFormatData.Initialize(&discRecorder, CLIENT_NAME))
  410. {
  411. // 获取当前媒体的大小;
  412. LONG ulCapity;
  413. discFormatData.GetFreeSectorsOnMedia(ulCapity);
  414. //
  415. // Get the media type currently in the recording device
  416. //
  417. IMAPI_MEDIA_PHYSICAL_TYPE mediaType = IMAPI_MEDIA_TYPE_UNKNOWN;
  418. discFormatData.GetInterface()->get_CurrentPhysicalMediaType(&mediaType);
  419. //
  420. // Create the file system
  421. //
  422. IStream* dataStream = NULL;
  423. if (!CreateMediaFileSystem(pThis, mediaType, &dataStream))
  424. { // CreateMediaFileSystem reported error to UI
  425. return false;
  426. }
  427. discFormatData.SetCloseMedia(pThis->m_closeMedia ? true : false);
  428. //
  429. // Burn the data, this does all the work
  430. //
  431. discFormatData.Burn(pThis->m_hWnd, dataStream);
  432. //
  433. // Release the IStream after burning
  434. //
  435. dataStream->Release();
  436. //
  437. // Eject Media if they chose
  438. //
  439. if (pThis->m_ejectWhenFinished)
  440. {
  441. discRecorder.EjectMedia();
  442. }
  443. }
  444. // 释放独占的访问权限;
  445. discRecorder.ReleaseExclusiveAccess();
  446. //
  447. // Finished Burning, GetHresult will determine if it was successful or not
  448. //
  449. pThis->SendMessage(WM_BURN_FINISHED, discFormatData.GetHresult(),
  450. (LPARAM)(LPCTSTR)discFormatData.GetErrorMessage());
  451. }
  452. else
  453. {
  454. // 检索对设备具有独占访问权限的用户的名称
  455. errorMessage.Format(_T("Failed: %s is exclusive owner"),(LPCTSTR)discRecorder.ExclusiveAccessOwner());
  456. pThis->SendMessage(WM_BURN_FINISHED, discRecorder.GetHresult(), (LPARAM)(LPCTSTR)errorMessage);
  457. }
  458. }
  459. else
  460. {
  461. errorMessage.Format(_T("Failed to initialize recorder - Unique ID:%s"),(LPCTSTR)pOrigDiscRecorder->GetUniqueId());
  462. pThis->SendMessage(WM_BURN_FINISHED, discRecorder.GetHresult(), (LPARAM)(LPCTSTR)errorMessage);
  463. }
  464. return 0;
  465. }
  466. /////////////////////////////////////////////////////////////////////////////
  467. //
  468. // CBurnCDDlg::CreateMediaFileSystem
  469. //
  470. // Description
  471. // Creates an IStream used to
  472. //
  473. bool CBurnCDDlg::CreateMediaFileSystem(CBurnCDDlg* pThis, IMAPI_MEDIA_PHYSICAL_TYPE mediaType, IStream** ppDataStream)
  474. {
  475. IFileSystemImage* image = NULL;
  476. IFileSystemImageResult* imageResult = NULL;
  477. IFsiDirectoryItem* rootItem = NULL;
  478. CString message;
  479. bool returnVal = false;
  480. HRESULT hr = CoCreateInstance(CLSID_MsftFileSystemImage,NULL, CLSCTX_ALL, __uuidof(IFileSystemImage), (void**)&image);
  481. if (FAILED(hr) || (image == NULL))
  482. {
  483. pThis->SendMessage(WM_BURN_FINISHED, hr,
  484. (LPARAM)_T("Failed to create IFileSystemImage Interface"));
  485. return false;
  486. }
  487. pThis->SendMessage(WM_BURN_STATUS_MESSAGE, 0, (LPARAM)_T("Creating File System..."));
  488. image->put_FileSystemsToCreate((FsiFileSystems)(FsiFileSystemJoliet|FsiFileSystemISO9660));
  489. image->put_VolumeName(pThis->m_volumeLabel.AllocSysString());
  490. image->ChooseImageDefaultsForMediaType(mediaType);
  491. //
  492. // Get the image root
  493. //
  494. hr = image->get_Root(&rootItem);
  495. if (SUCCEEDED(hr))
  496. {
  497. //
  498. // Add Files and Directories to File System Image
  499. //
  500. int itemCount = pThis->m_fileListbox.GetCount();
  501. for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
  502. {
  503. CBaseObject* pObject = (CBaseObject*)pThis->m_fileListbox.GetItemDataPtr(itemIndex);
  504. ASSERT(pObject != NULL);
  505. if (pObject == NULL)
  506. continue;
  507. CString fileName = pObject->GetName();
  508. message.Format(_T("Adding \"%s\" to file system..."), (LPCTSTR)fileName);
  509. pThis->SendMessage(WM_BURN_STATUS_MESSAGE, 0, (LPARAM)(LPCTSTR)message);
  510. if (pObject->IsKindOf(RUNTIME_CLASS(CFileObject)))
  511. {
  512. CFileObject* pFileObject = (CFileObject*)pObject;
  513. IStream* fileStream = pFileObject->GetStream();
  514. if (fileStream != NULL)
  515. {
  516. hr = rootItem->AddFile(pFileObject->GetName().AllocSysString(), fileStream);
  517. if (FAILED(hr))
  518. {
  519. // IMAPI_E_IMAGE_SIZE_LIMIT 0xc0aab120
  520. message.Format(_T("Failed IFsiDirectoryItem->AddFile(%s)!"),
  521. (LPCTSTR)pFileObject->GetName());
  522. pThis->SendMessage(WM_BURN_FINISHED, hr, (LPARAM)(LPCTSTR)message);
  523. break;
  524. }
  525. }
  526. }
  527. else if (pObject->IsKindOf(RUNTIME_CLASS(CDirObject)))
  528. {
  529. CDirObject* pDirObject = (CDirObject*)pObject;
  530. hr = rootItem->AddTree(pDirObject->GetPath().AllocSysString(), VARIANT_TRUE);
  531. if (FAILED(hr))
  532. {
  533. // IMAPI_E_IMAGE_SIZE_LIMIT 0xc0aab120
  534. message.Format(_T("Failed IFsiDirectoryItem->AddTree(%s)!"),
  535. (LPCTSTR)pDirObject->GetName());
  536. pThis->SendMessage(WM_BURN_FINISHED, hr, (LPARAM)(LPCTSTR)message);
  537. break;
  538. }
  539. }
  540. //
  541. // Did user cancel?
  542. //
  543. if (pThis->GetCancelBurning())
  544. {
  545. pThis->SendMessage(WM_BURN_FINISHED, 0, (LPARAM)_T("User Canceled!"));
  546. hr = IMAPI_E_FSI_INTERNAL_ERROR;
  547. }
  548. }
  549. if (SUCCEEDED(hr))
  550. {
  551. // Create the result image
  552. hr = image->CreateResultImage(&imageResult);
  553. if (SUCCEEDED(hr))
  554. {
  555. //
  556. // Get the stream
  557. //
  558. hr = imageResult->get_ImageStream(ppDataStream);
  559. if (SUCCEEDED(hr))
  560. {
  561. returnVal = true;
  562. }
  563. else
  564. {
  565. pThis->SendMessage(WM_BURN_FINISHED, hr,
  566. (LPARAM)_T("Failed IFileSystemImageResult->get_ImageStream!"));
  567. }
  568. }
  569. else
  570. {
  571. pThis->SendMessage(WM_BURN_FINISHED, hr,
  572. (LPARAM)_T("Failed IFileSystemImage->CreateResultImage!"));
  573. }
  574. }
  575. }
  576. else
  577. {
  578. pThis->SendMessage(WM_BURN_FINISHED, hr, (LPARAM)_T("Failed IFileSystemImage->getRoot"));
  579. }
  580. //
  581. // Cleanup
  582. //
  583. if (image != NULL)
  584. image->Release();
  585. if (imageResult != NULL)
  586. imageResult->Release();
  587. if (rootItem != NULL)
  588. rootItem->Release();
  589. return returnVal;
  590. }
  591. LRESULT CBurnCDDlg::OnBurnStatusMessage(WPARAM, LPARAM lpMessage)
  592. {
  593. if (lpMessage != NULL)
  594. {
  595. m_progressText.SetWindowText((LPCTSTR)lpMessage);
  596. }
  597. return 0;
  598. }
  599. LRESULT CBurnCDDlg::OnBurnFinished(WPARAM hResult, LPARAM lpMessage)
  600. {
  601. if (lpMessage != NULL)
  602. {
  603. if (SUCCEEDED((HRESULT)hResult))
  604. {
  605. m_progressText.SetWindowText((LPCTSTR)lpMessage);
  606. }
  607. else
  608. {
  609. CString text;
  610. text.Format(_T("%s - Error:0x%08X"), (LPCTSTR)lpMessage, hResult);
  611. m_progressText.SetWindowText(text);
  612. }
  613. }
  614. else
  615. {
  616. if (SUCCEEDED((HRESULT)hResult))
  617. {
  618. m_progressText.SetWindowText(_T("Burn completed successfully!"));
  619. }
  620. else
  621. {
  622. CString message;
  623. message.Format(_T("Burn failed! Error: 0x%08x"), hResult);
  624. m_progressText.SetWindowText(message);
  625. }
  626. }
  627. EnableUI(TRUE);
  628. return 0;
  629. }
  630. LRESULT CBurnCDDlg::OnImapiUpdate(WPARAM wParam, LPARAM lParam)
  631. {
  632. IMAPI_FORMAT2_DATA_WRITE_ACTION currentAction =
  633. (IMAPI_FORMAT2_DATA_WRITE_ACTION)wParam;
  634. PIMAPI_STATUS pImapiStatus = (PIMAPI_STATUS)lParam;
  635. switch (currentAction)
  636. {
  637. case IMAPI_FORMAT2_DATA_WRITE_ACTION_VALIDATING_MEDIA:
  638. m_progressText.SetWindowText(_T("Validating current media..."));
  639. break;
  640. case IMAPI_FORMAT2_DATA_WRITE_ACTION_FORMATTING_MEDIA:
  641. m_progressText.SetWindowText(_T("Formatting media..."));
  642. break;
  643. case IMAPI_FORMAT2_DATA_WRITE_ACTION_INITIALIZING_HARDWARE:
  644. m_progressText.SetWindowText(_T("Initializing hardware..."));
  645. break;
  646. case IMAPI_FORMAT2_DATA_WRITE_ACTION_CALIBRATING_POWER:
  647. m_progressText.SetWindowText(_T("Optimizing laser intensity..."));
  648. break;
  649. case IMAPI_FORMAT2_DATA_WRITE_ACTION_WRITING_DATA:
  650. UpdateTimes(pImapiStatus->totalTime, pImapiStatus->remainingTime);
  651. UpdateBuffer(pImapiStatus->usedSystemBuffer, pImapiStatus->totalSystemBuffer);
  652. UpdateProgress(pImapiStatus->lastWrittenLba-pImapiStatus->startLba, pImapiStatus->sectorCount);
  653. break;
  654. case IMAPI_FORMAT2_DATA_WRITE_ACTION_FINALIZATION:
  655. m_progressText.SetWindowText(_T("Finalizing writing..."));
  656. break;
  657. case IMAPI_FORMAT2_DATA_WRITE_ACTION_COMPLETED:
  658. m_progressText.SetWindowText(_T("Completed!"));
  659. break;
  660. }
  661. return GetCancelBurning() ? RETURN_CANCEL_WRITE : RETURN_CONTINUE;
  662. }
  663. void CBurnCDDlg::UpdateTimes(LONG totalTime, LONG remainingTime)
  664. {
  665. //
  666. // Set the estimated total time
  667. //
  668. CString strText;
  669. if (totalTime > 0)
  670. {
  671. strText.Format(_T("%d:%02d"), totalTime / 60, totalTime % 60);
  672. }
  673. else
  674. {
  675. strText = _T("0:00");
  676. }
  677. m_estimatedTime.SetWindowText(strText);
  678. //
  679. // Set the estimated remaining time
  680. //
  681. if (remainingTime > 0)
  682. {
  683. strText.Format(_T("%d:%02d"), remainingTime / 60, remainingTime % 60);
  684. }
  685. else
  686. {
  687. strText = _T("0:00");
  688. }
  689. m_timeLeft.SetWindowText(strText);
  690. }
  691. void CBurnCDDlg::UpdateBuffer(LONG usedSystemBuffer, LONG totalSystemBuffer)
  692. {
  693. CString text;
  694. if (usedSystemBuffer && totalSystemBuffer)
  695. {
  696. m_bufferCtrl.SetRange32(0, totalSystemBuffer);
  697. m_bufferCtrl.SetPos(usedSystemBuffer);
  698. text.Format(_T("Buffer: %d%%"), (100*usedSystemBuffer) / totalSystemBuffer);
  699. }
  700. else
  701. {
  702. text = _T("Buffer Empty");
  703. m_bufferCtrl.SetPos(0);
  704. }
  705. m_bufferText.SetWindowText(text);
  706. }
  707. void CBurnCDDlg::UpdateProgress(LONG writtenSectors, LONG totalSectors)
  708. {
  709. static LONG prevTotalSector = 0;
  710. CString text;
  711. if (totalSectors && (totalSectors != prevTotalSector))
  712. {
  713. prevTotalSector = totalSectors;
  714. m_progressCtrl.SetRange32(0, totalSectors);
  715. }
  716. m_progressCtrl.SetPos(writtenSectors);
  717. if (writtenSectors && totalSectors)
  718. {
  719. text.Format(_T("Progress: %d%%"), (100*writtenSectors) / totalSectors);
  720. }
  721. else
  722. {
  723. text = _T("Progress");
  724. }
  725. m_progressText.SetWindowText(text);
  726. }
  727. void CBurnCDDlg::OnCbnSelchangeMediaTypeCombo()
  728. {
  729. int selectedIndex = m_mediaTypeCombo.GetCurSel();
  730. if (selectedIndex == -1)
  731. {
  732. m_selectedMediaType = -1;
  733. }
  734. else
  735. {
  736. m_selectedMediaType = (int)m_mediaTypeCombo.GetItemData(selectedIndex);
  737. }
  738. UpdateCapacity();
  739. }
  740. void CBurnCDDlg::UpdateCapacity()
  741. {
  742. //
  743. // Set the selected media type data
  744. //
  745. ULONGLONG totalSize = 0;
  746. CString maxText;
  747. if (m_selectedMediaType == CD_MEDIA)
  748. {
  749. maxText = _T("700MB");
  750. totalSize = 700000000;
  751. }
  752. else if (m_selectedMediaType == DVD_MEDIA)
  753. {
  754. maxText = _T("4.7GB");
  755. totalSize = 4700000000;
  756. }
  757. else if (m_selectedMediaType == DL_DVD_MEDIA)
  758. {
  759. maxText = _T("8.5GB");
  760. totalSize = 8500000000;
  761. }
  762. m_maxText.SetWindowText(maxText);
  763. //
  764. // Calculate the size of the files
  765. //
  766. ULONGLONG mediaSize = 0;
  767. int itemCount = m_fileListbox.GetCount();
  768. for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
  769. {
  770. CBaseObject* pObject = (CBaseObject*)m_fileListbox.GetItemDataPtr(itemIndex);
  771. mediaSize += pObject->GetSizeOnDisc();
  772. }
  773. m_capacityProgress.SetRange(0,100);
  774. if (mediaSize == 0)
  775. {
  776. m_capacityProgress.SetPos(0);
  777. #if _MFC_VER >= 0x0900
  778. m_capacityProgress.SetState(PBST_NORMAL);
  779. #endif
  780. }
  781. else
  782. {
  783. int percent = (int)((mediaSize*100)/totalSize);
  784. if (percent > 100)
  785. {
  786. m_capacityProgress.SetPos(100);
  787. #if _MFC_VER >= 0x0900
  788. m_capacityProgress.SetState(PBST_ERROR);
  789. #endif
  790. }
  791. else
  792. {
  793. m_capacityProgress.SetPos(percent);
  794. #if _MFC_VER >= 0x0900
  795. m_capacityProgress.SetState(PBST_NORMAL);
  796. #endif
  797. }
  798. }
  799. }
  800. void CBurnCDDlg::EnableBurnButton()
  801. {
  802. GetDlgItem(IDC_BURN_BUTTON)->EnableWindow(m_fileListbox.GetCount()>0);
  803. }
  804. void CBurnCDDlg::OnBnClickedRemoveFilesButton()
  805. {
  806. int currentSelection = m_fileListbox.GetCurSel();
  807. ASSERT(currentSelection != -1);
  808. if (currentSelection == -1)
  809. return;
  810. CBaseObject* pBaseObject = (CBaseObject*)m_fileListbox.GetItemDataPtr(currentSelection);
  811. if (pBaseObject == NULL)
  812. return;
  813. CString message;
  814. message.Format(_T("Are you sure you want to remove \"%s\"?"), (LPCTSTR)pBaseObject->GetName());
  815. if (AfxMessageBox(message, MB_YESNO|MB_ICONQUESTION) == IDYES)
  816. {
  817. m_fileListbox.DeleteString(currentSelection);
  818. delete pBaseObject;
  819. OnLbnSelchangeBurnFileList();
  820. EnableBurnButton();
  821. UpdateCapacity();
  822. }
  823. }
  824. void CBurnCDDlg::EnableUI(BOOL bEnable)
  825. {
  826. m_deviceComboBox.EnableWindow(bEnable);
  827. m_fileListbox.EnableWindow(bEnable);
  828. m_mediaTypeCombo.EnableWindow(bEnable);
  829. GetDlgItem(IDC_ADD_FILES_BUTTON)->EnableWindow(bEnable);
  830. GetDlgItem(IDC_ADD_FOLDER_BUTTON)->EnableWindow(bEnable);
  831. GetDlgItem(IDC_REMOVE_FILES_BUTTON)->EnableWindow(bEnable);
  832. GetDlgItem(IDCANCEL)->EnableWindow(bEnable);
  833. GetDlgItem(IDC_EJECT_WHEN_FINISHED)->EnableWindow(bEnable);
  834. GetDlgItem(IDC_CLOSE_MEDIA_CHK)->EnableWindow(bEnable);
  835. GetDlgItem(IDC_VOLUME)->EnableWindow(bEnable);
  836. GetDlgItem(IDC_BURN_BUTTON)->SetWindowText(bEnable ?
  837. _T("Burn") : _T("Cancel"));
  838. }
  839. void CBurnCDDlg::SetCancelBurning(bool bCancel)
  840. {
  841. CSingleLock singleLock(&m_critSection);
  842. m_cancelBurn = bCancel;
  843. }
  844. bool CBurnCDDlg::GetCancelBurning()
  845. {
  846. CSingleLock singleLock(&m_critSection);
  847. return m_cancelBurn;
  848. }