Jeff 6 жил өмнө
parent
commit
3e1fa22ad1
100 өөрчлөгдсөн 13586 нэмэгдсэн , 0 устгасан
  1. 179 0
      Burndiscs/BurndiscTest/BurndiscTest.cpp
  2. 32 0
      Burndiscs/BurndiscTest/BurndiscTest.h
  3. 197 0
      Burndiscs/BurndiscTest/BurndiscTest.rc
  4. 380 0
      Burndiscs/BurndiscTest/BurndiscTest.vcproj
  5. 173 0
      Burndiscs/BurndiscTest/BurndiscTest.vcxproj
  6. 141 0
      Burndiscs/BurndiscTest/BurndiscTest.vcxproj.filters
  7. 153 0
      Burndiscs/BurndiscTest/BurndiscTestDlg.cpp
  8. 32 0
      Burndiscs/BurndiscTest/BurndiscTestDlg.h
  9. 69 0
      Burndiscs/BurndiscTest/ReadMe.txt
  10. 21 0
      Burndiscs/BurndiscTest/Resource.h
  11. BIN
      Burndiscs/BurndiscTest/dll/libiconv_md.lib
  12. BIN
      Burndiscs/BurndiscTest/dll/libiconv_mdd.lib
  13. BIN
      Burndiscs/BurndiscTest/dll/libiconv_mt.lib
  14. BIN
      Burndiscs/BurndiscTest/dll/libiconv_mtd.lib
  15. 259 0
      Burndiscs/BurndiscTest/iconv.h
  16. 293 0
      Burndiscs/BurndiscTest/iconv_impl.cpp
  17. 13 0
      Burndiscs/BurndiscTest/iconv_impl.h
  18. BIN
      Burndiscs/BurndiscTest/lib/libiconv_md.lib
  19. BIN
      Burndiscs/BurndiscTest/lib/libiconv_mdd.lib
  20. BIN
      Burndiscs/BurndiscTest/lib/libiconv_mt.lib
  21. BIN
      Burndiscs/BurndiscTest/lib/libiconv_mtd.lib
  22. BIN
      Burndiscs/BurndiscTest/res/BurndiscTest.ico
  23. 13 0
      Burndiscs/BurndiscTest/res/BurndiscTest.rc2
  24. 119 0
      Burndiscs/BurndiscTest/stdafx.cpp
  25. 178 0
      Burndiscs/BurndiscTest/stdafx.h
  26. 26 0
      Burndiscs/BurndiscTest/targetver.h
  27. 120 0
      Burndiscs/BurndiscTest2/BurndiscTest2.cpp
  28. 32 0
      Burndiscs/BurndiscTest2/BurndiscTest2.h
  29. 197 0
      Burndiscs/BurndiscTest2/BurndiscTest2.rc
  30. 270 0
      Burndiscs/BurndiscTest2/BurndiscTest2.vcproj
  31. 145 0
      Burndiscs/BurndiscTest2/BurndiscTest2.vcxproj
  32. 63 0
      Burndiscs/BurndiscTest2/BurndiscTest2.vcxproj.filters
  33. 153 0
      Burndiscs/BurndiscTest2/BurndiscTest2Dlg.cpp
  34. 32 0
      Burndiscs/BurndiscTest2/BurndiscTest2Dlg.h
  35. 101 0
      Burndiscs/BurndiscTest2/IBurndisc.h
  36. 27 0
      Burndiscs/BurndiscTest2/Nero.h
  37. 69 0
      Burndiscs/BurndiscTest2/ReadMe.txt
  38. 21 0
      Burndiscs/BurndiscTest2/Resource.h
  39. BIN
      Burndiscs/BurndiscTest2/res/BurndiscTest2.ico
  40. 13 0
      Burndiscs/BurndiscTest2/res/BurndiscTest2.rc2
  41. 178 0
      Burndiscs/BurndiscTest2/stdafx.cpp
  42. 92 0
      Burndiscs/BurndiscTest2/stdafx.h
  43. 26 0
      Burndiscs/BurndiscTest2/targetver.h
  44. 36 0
      Burndiscs/Burndiscs - 17.sln
  45. 31 0
      Burndiscs/Burndiscs.sln
  46. 95 0
      Burndiscs/Burndiscs/Burndiscs.cpp
  47. 7 0
      Burndiscs/Burndiscs/Burndiscs.def
  48. 27 0
      Burndiscs/Burndiscs/Burndiscs.h
  49. 125 0
      Burndiscs/Burndiscs/Burndiscs.rc
  50. 381 0
      Burndiscs/Burndiscs/Burndiscs.vcproj
  51. 178 0
      Burndiscs/Burndiscs/Burndiscs.vcxproj
  52. 139 0
      Burndiscs/Burndiscs/Burndiscs.vcxproj.filters
  53. 364 0
      Burndiscs/Burndiscs/DiscFormatData.cpp
  54. 86 0
      Burndiscs/Burndiscs/DiscFormatData.h
  55. 220 0
      Burndiscs/Burndiscs/DiscFormatDataEvent.cpp
  56. 70 0
      Burndiscs/Burndiscs/DiscFormatDataEvent.h
  57. 134 0
      Burndiscs/Burndiscs/DiscMaster.cpp
  58. 41 0
      Burndiscs/Burndiscs/DiscMaster.h
  59. 395 0
      Burndiscs/Burndiscs/DiscRecorder.cpp
  60. 63 0
      Burndiscs/Burndiscs/DiscRecorder.h
  61. 3 0
      Burndiscs/Burndiscs/IBurndisc.cpp
  62. 101 0
      Burndiscs/Burndiscs/IBurndisc.h
  63. 897 0
      Burndiscs/Burndiscs/IMAPI2Impl.cpp
  64. 86 0
      Burndiscs/Burndiscs/IMAPI2Impl.h
  65. 27 0
      Burndiscs/Burndiscs/Nero.h
  66. 113 0
      Burndiscs/Burndiscs/Nero/Include/APIRoboControl.h
  67. 1794 0
      Burndiscs/Burndiscs/Nero/Include/NeroAPI.h
  68. 72 0
      Burndiscs/Burndiscs/Nero/Include/NeroAPIGlue.h
  69. 180 0
      Burndiscs/Burndiscs/Nero/Include/NeroBurnAtOnce.h
  70. 84 0
      Burndiscs/Burndiscs/Nero/Include/NeroCopyAPI.h
  71. 298 0
      Burndiscs/Burndiscs/Nero/Include/NeroFileSystemContent.h
  72. 69 0
      Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockAccessExtensions.h
  73. 44 0
      Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockAccessInterface.h
  74. 95 0
      Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockReaderInterface.h
  75. 68 0
      Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockWriterInterface.h
  76. 258 0
      Burndiscs/Burndiscs/Nero/Include/NeroIsoTrack.h
  77. 92 0
      Burndiscs/Burndiscs/Nero/Include/NeroPacketWriting.h
  78. 495 0
      Burndiscs/Burndiscs/Nero/Include/NeroUserDialog.h
  79. BIN
      Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlue.lib
  80. BIN
      Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlueBCPPB.lib
  81. BIN
      Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlueRT.lib
  82. 10 0
      Burndiscs/Burndiscs/Nero/Lib/Readme.txt
  83. BIN
      Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlue.lib
  84. BIN
      Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlueBCPPB.lib
  85. BIN
      Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlueRT.lib
  86. 11 0
      Burndiscs/Burndiscs/Nero/Lib/VS6/Readme.txt
  87. 191 0
      Burndiscs/Burndiscs/NeroBurndisc.cpp
  88. 76 0
      Burndiscs/Burndiscs/NeroBurndisc.h
  89. 403 0
      Burndiscs/Burndiscs/NeroDevice.cpp
  90. 61 0
      Burndiscs/Burndiscs/NeroDevice.h
  91. 653 0
      Burndiscs/Burndiscs/NeroImpl.cpp
  92. 109 0
      Burndiscs/Burndiscs/NeroImpl.h
  93. 914 0
      Burndiscs/Burndiscs/NeroItem.cpp
  94. 69 0
      Burndiscs/Burndiscs/NeroItem.h
  95. 10 0
      Burndiscs/Burndiscs/NeroMedia.cpp
  96. 34 0
      Burndiscs/Burndiscs/NeroMedia.h
  97. 44 0
      Burndiscs/Burndiscs/ReadMe.txt
  98. 16 0
      Burndiscs/Burndiscs/Resource.h
  99. BIN
      Burndiscs/Burndiscs/dll/libiconv_md.lib
  100. BIN
      Burndiscs/Burndiscs/dll/libiconv_mdd.lib

+ 179 - 0
Burndiscs/BurndiscTest/BurndiscTest.cpp

@@ -0,0 +1,179 @@
+
+// BurndiscTest.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "BurndiscTest.h"
+#include "BurndiscTestDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CBurndiscTestApp
+
+BEGIN_MESSAGE_MAP(CBurndiscTestApp, CWinAppEx)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CBurndiscTestApp 构造
+
+CBurndiscTestApp::CBurndiscTestApp()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CBurndiscTestApp 对象
+
+CBurndiscTestApp theApp;
+
+
+// CBurndiscTestApp 初始化
+
+BOOL CBurndiscTestApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+	AfxEnableControlContainer();
+
+#if 0
+	CNeroBurndisc NeroCtrl;
+	if (NeroCtrl.NeroAPIInit())
+	{
+		if (NeroCtrl.GetAvailableDrives() > 0)
+		{
+			CNeroDevice neroDev;
+			if (neroDev.OpenDevice(NeroCtrl.GetDeviceInfs(), 0))
+			{
+				// 获取媒体信息;
+				NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(neroDev.GetDeviceHandle(), NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC);
+				if (pNeroCDInfo == NULL)
+					return FALSE;
+
+				// 媒体光盘大小 = Blocks * BlockSize;
+				unsigned __int64 MediaSize = ((__int64(pNeroCDInfo->ncdiTotalCapacity)) * pNeroCDInfo->ncdiTrackInfos[0].ntiBlockSize) / 1024 / 1024;
+
+				NERO_MEDIA_TYPE MediaType = NeroGetCurrentMediumType(neroDev.GetDeviceHandle());
+
+				// 写速度;
+				NERO_SPEED_INFOS *pnsiWrite = NeroGetAvailableSpeeds(neroDev.GetDeviceHandle(), ACCESSTYPE_WRITE, pNeroCDInfo->ncdiMediaType, NULL);
+
+				// 读速度;
+				NERO_SPEED_INFOS *pnsiRead = NeroGetAvailableSpeeds(neroDev.GetDeviceHandle(), ACCESSTYPE_READ, pNeroCDInfo->ncdiMediaType, NULL);
+			}
+		}
+	}
+#else
+	//_CrtSetBreakAlloc(255); //98500为上面内存泄漏的块号.
+
+#if 0
+	CDiscItem discitem;
+	discitem.InitVituralItem();
+	discitem.AddPath(_T("E:\\aaaa\\bbbb\\cccc\\"));
+	discitem.AddPath(_T("E:\\aaaa\\bbbb\\eeeee\\"));
+	discitem.AddPath(_T("E:\\aaaa\\bbbb\\gggggg\\"));
+	discitem.AddPath(_T("E:\\aaaa\\bbbb\\jjjjjj\\tttttt"));
+
+	NERO_ISO_ITEM *pItem = discitem.FindPathItem(_T("E:\\aaaa\\bbbb\\jjjjjj\\tttttt"));
+
+	pItem = discitem.FindPathItem(_T("jjjjjj"));
+
+	pItem = discitem.FindPathItem(_T("llll"));
+	return FALSE;
+#endif
+
+	IBurndisc *pBurndisc = new CIMAPI2Impl();
+	pBurndisc->AddRef();
+
+#if NEROIMPL
+	CNeroImpl::m_pDailog = NULL;
+	CNeroImpl::m_pIdelCallback = _IdleCallback;
+	CNeroImpl::m_pUserDialog = _UserDialog;
+	CNeroImpl::m_pProgressCallback = _ProgressCallback;
+	CNeroImpl::m_pSubTaskProgressCallback = _ProgressCallback;
+	CNeroImpl::m_pAbortedCallback = _AbortedCallback;
+	CNeroImpl::m_pAddLogLine = _AddLogLine;
+	CNeroImpl::m_pSetPhaseCallback = _SetPhaseCallback;
+	CNeroImpl::m_pDisableAbortCallback = _DisableAbortCallback;
+	CNeroImpl::m_pSetMajorPhaseCallback = _SetMajorPhaseCallback;
+	CNeroImpl::m_pWriteIOCallback = _WriteIOCallback;
+	CNeroImpl::m_pReadIOCallback = _ReadIOCallback;
+	CNeroImpl::m_pEOFCallback = _EOFCallback;
+	CNeroImpl::m_pErrorCallback = _ErrorCallback;
+#endif
+
+	if (pBurndisc->Initialize()) {
+		pBurndisc->GetAvailableDrives();
+
+		pDeviceInfo pdvinfo = (pDeviceInfo)pBurndisc->GetDeivceInfo(_T("f:\\PIONEER  DVD-RW DVR-XU01 "));
+		if (pdvinfo)
+		{
+			pdvinfo->nIndex;
+			pdvinfo->strDevName;
+			OutputDebugString(pdvinfo->strDevName.c_str());
+		}
+#if 1
+		// 添加文件;
+		vector<TString> vtfiles;
+		filehelpImpl fhelp;
+		fhelp.getfiles_findout_subfolder(_T("E:\\测试相片"), _T("*.*"), &vtfiles);
+		pBurndisc->AddFiles2Disc(_T("aaaa4"), vtfiles);
+		//pBurndisc->AddFiles2Disc(_T("cccc2"), vtfiles);
+		//pBurndisc->AddFiles2Disc(_T("aaaa"), vtfiles);
+		//pBurndisc->AddFiles2Disc(_T("bbbbb"), vtfiles);
+		//pBurndisc->AddFiles2Disc(_T(""), vtfiles);
+#endif
+		//pBurndisc->AddFolder2Disc(_T("xxxx3"),_T("E:\\测试相片"));
+		//pBurndisc->AddFolder2Disc(_T("xxxx3"),_T("E:\\测试相片2"));
+		//pBurndisc->AddFolder2Disc(_T("xxxx2"),_T("E:\\测试相片"));
+		//pBurndisc->AddFolder2Disc(_T("eeeee"),_T("E:\\测试相片"));
+		pBurndisc->AddFolder2Disc(_T("www24"), _T("E:\\测试相片2"));
+
+		pBurndisc->BurnMedia(0, _T("aaaa"), _T("标题:利亚方舟"));
+	}
+
+	pBurndisc->Release();
+	pBurndisc = NULL;
+#endif
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+	CBurndiscTestDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}

+ 32 - 0
Burndiscs/BurndiscTest/BurndiscTest.h

@@ -0,0 +1,32 @@
+
+// BurndiscTest.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CBurndiscTestApp:
+// 有关此类的实现,请参阅 BurndiscTest.cpp
+//
+
+class CBurndiscTestApp : public CWinAppEx
+{
+public:
+	CBurndiscTestApp();
+
+// 重写
+	public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CBurndiscTestApp theApp;

+ 197 - 0
Burndiscs/BurndiscTest/BurndiscTest.rc

@@ -0,0 +1,197 @@
+// Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+	"#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+    "LANGUAGE 4, 2\r\n"
+    "#pragma code_page(936)\r\n"
+    "#include ""res\\BurndiscTest.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+    "#include ""l.CHS\\afxres.rc""  	// 标准组件\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 图标
+//
+
+// ID 值最低的图标放在最前面,以确保应用程序图标
+// 在所有系统中保持一致。
+IDR_MAINFRAME           ICON         "res\\BurndiscTest.ico"
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 对话框
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "关于 BurndiscTest"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
+    LTEXT           "BurndiscTest,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2018",IDC_STATIC,42,26,114,8
+    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
+END
+
+IDD_BURNDISCTEST_DIALOG DIALOGEX  0, 0, 320, 200
+STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION
+ | DS_MODALFRAME
+ | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "BurndiscTest"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    DEFPUSHBUTTON   "确定",IDOK,209,179,50,14
+    PUSHBUTTON      "取消",IDCANCEL,263,179,50,14
+	CTEXT           "TODO: 在此放置对话框控件。",IDC_STATIC,10,96,300,8
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 版本
+//
+
+VS_VERSION_INFO     VERSIONINFO
+  FILEVERSION       1,0,0,1
+  PRODUCTVERSION    1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+        BLOCK "080403a8"
+		BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+			VALUE "FileVersion",     "1.0.0.1"
+			VALUE "InternalName",    "BurndiscTest.exe"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+			VALUE "OriginalFilename","BurndiscTest.exe"
+            VALUE "ProductName", "TODO: <产品名>"
+			VALUE "ProductVersion",  "1.0.0.1"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x0804, 936
+    END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 163
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 55
+    END
+    IDD_BURNDISCTEST_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 313
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 193
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+    IDS_ABOUTBOX            "关于 BurndiscTest(&A)..."
+END
+
+
+#endif
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\\BurndiscTest.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#include "l.CHS\\afxres.rc"  	// 标准组件
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED
+

+ 380 - 0
Burndiscs/BurndiscTest/BurndiscTest.vcproj

@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="BurndiscTest"
+	ProjectGUID="{40158659-BABD-4316-9F9F-9771E5228126}"
+	RootNamespace="BurndiscTest"
+	Keyword="MFCProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\Burndiscs\Nero\Include;&quot;..\STL-findfile&quot;"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="NeroAPIGlue.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\Burndiscs\Nero\Lib"
+				IgnoreDefaultLibraryNames="libcmt.lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\Burndiscs\Nero\Include;&quot;..\STL-findfile&quot;"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;LIBICONV_EXPORTS;BUILDING_LIBICONV;BUILDING_LIBCHARSET;USE_STATIC_ICONV"
+				MinimalRebuild="false"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="NeroAPIGlue.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\Burndiscs\Nero\Lib"
+				IgnoreDefaultLibraryNames="libcmt.lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\BurndiscTest.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTestDlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\BurndiscTest.h"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTestDlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\res\BurndiscTest.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTest.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\BurndiscTest.rc2"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Nero"
+			>
+			<File
+				RelativePath="..\Burndiscs\IBurndisc.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\Nero.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\NeroImpl.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\NeroImpl.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\NeroItem.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\NeroItem.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="iconv"
+			>
+			<File
+				RelativePath=".\iconv_impl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\iconv_impl.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="filehelp"
+			>
+			<File
+				RelativePath="..\STL-findfile\filehelp.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\STL-findfile\filehelp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\STL-findfile\findfile.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\STL-findfile\findfile.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="IMAPI2"
+			>
+			<File
+				RelativePath="..\Burndiscs\DiscFormatData.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscFormatData.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscFormatDataEvent.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscFormatDataEvent.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscMaster.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscMaster.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscRecorder.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\DiscRecorder.h"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\IMAPI2Impl.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Burndiscs\IMAPI2Impl.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 173 - 0
Burndiscs/BurndiscTest/BurndiscTest.vcxproj

@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{40158659-BABD-4316-9F9F-9771E5228126}</ProjectGuid>
+    <RootNamespace>BurndiscTest</RootNamespace>
+    <Keyword>MFCProj</Keyword>
+    <WindowsTargetPlatformVersion>7.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141_xp</PlatformToolset>
+    <UseOfMfc>Static</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>15.0.27428.2015</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)</OutDir>
+    <IntDir>$(OutDir)\$(ProjectName)\$(Configuration)</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)</OutDir>
+    <IntDir>$(OutDir)\$(ProjectName)\$(Configuration)</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\Burndiscs\Nero\Include;..\STL-findfile;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>NeroAPIGlue.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>..\Burndiscs\Nero\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <AdditionalIncludeDirectories>..\Burndiscs\Nero\Include;..\STL-findfile;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;LIBICONV_EXPORTS;BUILDING_LIBICONV;BUILDING_LIBCHARSET;USE_STATIC_ICONV;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>false</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>NeroAPIGlue.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>..\Burndiscs\Nero\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\Burndiscs\DiscFormatData.cpp" />
+    <ClCompile Include="..\Burndiscs\DiscFormatDataEvent.cpp" />
+    <ClCompile Include="..\Burndiscs\DiscMaster.cpp" />
+    <ClCompile Include="..\Burndiscs\DiscRecorder.cpp" />
+    <ClCompile Include="..\Burndiscs\IMAPI2Impl.cpp" />
+    <ClCompile Include="..\Burndiscs\NeroImpl.cpp" />
+    <ClCompile Include="..\Burndiscs\NeroItem.cpp" />
+    <ClCompile Include="..\STL-findfile\filehelp.cpp" />
+    <ClCompile Include="..\STL-findfile\findfile.cpp" />
+    <ClCompile Include="BurndiscTest.cpp" />
+    <ClCompile Include="BurndiscTestDlg.cpp" />
+    <ClCompile Include="iconv_impl.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\Burndiscs\DiscFormatData.h" />
+    <ClInclude Include="..\Burndiscs\DiscFormatDataEvent.h" />
+    <ClInclude Include="..\Burndiscs\DiscMaster.h" />
+    <ClInclude Include="..\Burndiscs\DiscRecorder.h" />
+    <ClInclude Include="..\Burndiscs\IBurndisc.h" />
+    <ClInclude Include="..\Burndiscs\IMAPI2Impl.h" />
+    <ClInclude Include="..\Burndiscs\Nero.h" />
+    <ClInclude Include="..\Burndiscs\NeroImpl.h" />
+    <ClInclude Include="..\Burndiscs\NeroItem.h" />
+    <ClInclude Include="..\STL-findfile\filehelp.h" />
+    <ClInclude Include="..\STL-findfile\findfile.h" />
+    <ClInclude Include="BurndiscTest.h" />
+    <ClInclude Include="BurndiscTestDlg.h" />
+    <ClInclude Include="iconv_impl.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\BurndiscTest.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BurndiscTest.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BurndiscTest.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 141 - 0
Burndiscs/BurndiscTest/BurndiscTest.vcxproj.filters

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+    <Filter Include="Nero">
+      <UniqueIdentifier>{9119a388-a239-4388-be38-bdc5e69f0d77}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="iconv">
+      <UniqueIdentifier>{f079f149-4327-4090-9350-5e5f22682c0c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="filehelp">
+      <UniqueIdentifier>{da645810-caec-4c37-81c3-7b4aad2d7454}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="IMAPI2">
+      <UniqueIdentifier>{274079a7-c84a-4955-8875-7f85f11e335a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="BurndiscTest.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="BurndiscTestDlg.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\NeroImpl.cpp">
+      <Filter>Nero</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\NeroItem.cpp">
+      <Filter>Nero</Filter>
+    </ClCompile>
+    <ClCompile Include="iconv_impl.cpp">
+      <Filter>iconv</Filter>
+    </ClCompile>
+    <ClCompile Include="..\STL-findfile\filehelp.cpp">
+      <Filter>filehelp</Filter>
+    </ClCompile>
+    <ClCompile Include="..\STL-findfile\findfile.cpp">
+      <Filter>filehelp</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\DiscFormatData.cpp">
+      <Filter>IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\DiscFormatDataEvent.cpp">
+      <Filter>IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\DiscMaster.cpp">
+      <Filter>IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\DiscRecorder.cpp">
+      <Filter>IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Burndiscs\IMAPI2Impl.cpp">
+      <Filter>IMAPI2</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="BurndiscTest.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="BurndiscTestDlg.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\IBurndisc.h">
+      <Filter>Nero</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\Nero.h">
+      <Filter>Nero</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\NeroImpl.h">
+      <Filter>Nero</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\NeroItem.h">
+      <Filter>Nero</Filter>
+    </ClInclude>
+    <ClInclude Include="iconv_impl.h">
+      <Filter>iconv</Filter>
+    </ClInclude>
+    <ClInclude Include="..\STL-findfile\filehelp.h">
+      <Filter>filehelp</Filter>
+    </ClInclude>
+    <ClInclude Include="..\STL-findfile\findfile.h">
+      <Filter>filehelp</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\DiscFormatData.h">
+      <Filter>IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\DiscFormatDataEvent.h">
+      <Filter>IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\DiscMaster.h">
+      <Filter>IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\DiscRecorder.h">
+      <Filter>IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="..\Burndiscs\IMAPI2Impl.h">
+      <Filter>IMAPI2</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\BurndiscTest.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BurndiscTest.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BurndiscTest.rc2">
+      <Filter>资源文件</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+</Project>

+ 153 - 0
Burndiscs/BurndiscTest/BurndiscTestDlg.cpp

@@ -0,0 +1,153 @@
+
+// BurndiscTestDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "BurndiscTest.h"
+#include "BurndiscTestDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+	enum { IDD = IDD_ABOUTBOX };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+END_MESSAGE_MAP()
+
+
+// CBurndiscTestDlg 对话框
+
+
+
+
+CBurndiscTestDlg::CBurndiscTestDlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CBurndiscTestDlg::IDD, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CBurndiscTestDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CBurndiscTestDlg, CDialog)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+// CBurndiscTestDlg 消息处理程序
+
+BOOL CBurndiscTestDlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CBurndiscTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CBurndiscTestDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CBurndiscTestDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+

+ 32 - 0
Burndiscs/BurndiscTest/BurndiscTestDlg.h

@@ -0,0 +1,32 @@
+
+// BurndiscTestDlg.h : 头文件
+//
+
+#pragma once
+
+
+// CBurndiscTestDlg 对话框
+class CBurndiscTestDlg : public CDialog
+{
+// 构造
+public:
+	CBurndiscTestDlg(CWnd* pParent = NULL);	// 标准构造函数
+
+// 对话框数据
+	enum { IDD = IDD_BURNDISCTEST_DIALOG };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+};

+ 69 - 0
Burndiscs/BurndiscTest/ReadMe.txt

@@ -0,0 +1,69 @@
+================================================================================
+    MICROSOFT 基础类库: BurndiscTest 项目概述
+===============================================================================
+
+应用程序向导已为您创建此 BurndiscTest 应用程序。此应用程序不仅演示使用 Microsoft 基础类的基本知识,而且可作为编写应用程序的起点。
+
+此文件包含组成 BurndiscTest 应用程序的各个文件的内容摘要。
+
+BurndiscTest.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件。
+    它包含有关生成文件的 Visual C++ 版本的信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+BurndiscTest.h
+    这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CBurndiscTestApp 应用程序类。
+
+BurndiscTest.cpp
+    这是包含应用程序类 CBurndiscTestApp 的主要应用程序源文件。
+
+BurndiscTest.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
+
+res\BurndiscTest.ico
+    这是用作应用程序图标的图标文件。此图标包括在主要资源文件 BurndiscTest.rc 中。
+
+res\BurndiscTest.rc2
+    此文件包含不是由 Microsoft Visual C++ 编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+应用程序向导创建一个对话框类:
+
+BurndiscTestDlg.h,BurndiscTestDlg.cpp - 对话框
+    这些文件包含 CBurndiscTestDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 BurndiscTest.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他功能:
+
+ActiveX 控件
+    应用程序包括对使用 ActiveX 控件的支持。
+
+打印及打印预览支持
+    应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 BurndiscTest.pch 的预编译头(PCH)文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,它定义新资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+BurndiscTest.manifest
+	Windows XP 使用应用程序清单文件描述应用程序	对特定版本并行程序集的依赖性。加载程序使用此	信息从程序集缓存加载相应程序集或	从应用程序加载私有信息。应用程序清单可能作为	与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件包括在内以便重新发布,	也可能以资源的形式包括在该可执行文件中。
+/////////////////////////////////////////////////////////////////////////////
+
+其他注释:
+
+应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
+
+如果应用程序在共享 DLL 中使用 MFC,则将需要重新发布 MFC DLL。如果应用程序所用与操作系统的区域设置不同,则也将必须重新发布对应的本地化资源 MFC90XXX.DLL。
+有关这两个主题的详细信息,请参阅 MSDN 文档中有关重新发布 Visual C++ 应用程序的部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 21 - 0
Burndiscs/BurndiscTest/Resource.h

@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by BurndiscTest.rc
+//
+#define IDR_MAINFRAME					128
+#define IDM_ABOUTBOX					0x0010
+#define IDD_ABOUTBOX					100
+#define IDS_ABOUTBOX					101
+#define IDD_BURNDISCTEST_DIALOG				102
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE	129
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#define _APS_NEXT_COMMAND_VALUE		32771
+#endif
+#endif

BIN
Burndiscs/BurndiscTest/dll/libiconv_md.lib


BIN
Burndiscs/BurndiscTest/dll/libiconv_mdd.lib


BIN
Burndiscs/BurndiscTest/dll/libiconv_mt.lib


BIN
Burndiscs/BurndiscTest/dll/libiconv_mtd.lib


+ 259 - 0
Burndiscs/BurndiscTest/iconv.h

@@ -0,0 +1,259 @@
+/* Copyright (C) 1999-2003, 2005-2006, 2008-2011 Free Software Foundation, Inc.
+This file is part of the GNU LIBICONV Library.
+
+The GNU LIBICONV Library is free software; you can redistribute it
+and/or modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+The GNU LIBICONV Library is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU LIBICONV Library; see the file COPYING.LIB.
+If not, see <http://www.gnu.org/licenses/>.  */
+
+/* When installed, this file is called "iconv.h". */
+
+#ifndef _LIBICONV_H
+#define _LIBICONV_H
+
+#define _LIBICONV_VERSION 0x010F    /* version number: (major<<8) + minor */
+
+//#if HAVE_VISIBILITY && BUILDING_LIBICONV
+//#define LIBICONV_DLL_EXPORTED __attribute__((__visibility__("default")))
+//#else
+//#define LIBICONV_DLL_EXPORTED
+//#endif
+//extern LIBICONV_DLL_EXPORTED DLL_VARIABLE int _libiconv_version; /* Likewise */
+
+#if BUILDING_LIBICONV
+#define LIBICONV_DLL_EXPORTED __declspec(dllexport)
+#elif USING_STATIC_LIBICONV
+#define LIBICONV_DLL_EXPORTED
+#else
+#define LIBICONV_DLL_EXPORTED __declspec(dllimport)
+#endif
+
+extern LIBICONV_DLL_EXPORTED int _libiconv_version; /* Likewise */
+
+
+
+/* We would like to #include any system header file which could define
+iconv_t, 1. in order to eliminate the risk that the user gets compilation
+errors because some other system header file includes /usr/include/iconv.h
+which defines iconv_t or declares iconv after this file, 2. when compiling
+for LIBICONV_PLUG, we need the proper iconv_t type in order to produce
+binary compatible code.
+But gcc's #include_next is not portable. Thus, once libiconv's iconv.h
+has been installed in /usr/local/include, there is no way any more to
+include the original /usr/include/iconv.h. We simply have to get away
+without it.
+Ad 1. The risk that a system header file does
+#include "iconv.h"  or  #include_next "iconv.h"
+is small. They all do #include <iconv.h>.
+Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It
+has to be a scalar type because (iconv_t)(-1) is a possible return value
+from iconv_open().) */
+
+/* Define iconv_t ourselves. */
+#undef iconv_t
+#define iconv_t libiconv_t
+typedef void* iconv_t;
+
+/* Get size_t declaration.
+Get wchar_t declaration if it exists. */
+#include <stddef.h>
+
+/* Get errno declaration and values. */
+#include <errno.h>
+/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS,
+have EILSEQ in a different header.  On these systems, define EILSEQ
+ourselves. */
+#ifndef EILSEQ
+#define EILSEQ @EILSEQ@
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+	/* Allocates descriptor for code conversion from encoding ‘fromcode’ to
+	encoding ‘tocode’. */
+#ifndef LIBICONV_PLUG
+#define iconv_open libiconv_open
+#endif
+	extern LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode);
+
+	/* Converts, using conversion descriptor ‘cd’, at most ‘*inbytesleft’ bytes
+	starting at ‘*inbuf’, writing at most ‘*outbytesleft’ bytes starting at
+	‘*outbuf’.
+	Decrements ‘*inbytesleft’ and increments ‘*inbuf’ by the same amount.
+	Decrements ‘*outbytesleft’ and increments ‘*outbuf’ by the same amount. */
+#ifndef LIBICONV_PLUG
+#define iconv libiconv
+#endif
+	extern LIBICONV_DLL_EXPORTED size_t iconv (iconv_t cd, const char** inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);
+
+	/* Frees resources allocated for conversion descriptor ‘cd’. */
+#ifndef LIBICONV_PLUG
+#define iconv_close libiconv_close
+#endif
+	extern LIBICONV_DLL_EXPORTED int iconv_close (iconv_t cd);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifndef LIBICONV_PLUG
+
+/* Nonstandard extensions. */
+
+#if USE_MBSTATE_T
+#if BROKEN_WCHAR_H
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+<wchar.h>.
+BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+included before <wchar.h>.  */
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+#endif
+#include <wchar.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/* A type that holds all memory needed by a conversion descriptor.
+	A pointer to such an object can be used as an iconv_t. */
+	typedef struct {
+		void* dummy1[28];
+#if USE_MBSTATE_T
+		mbstate_t dummy2;
+#endif
+	} iconv_allocation_t;
+
+	/* Allocates descriptor for code conversion from encoding ‘fromcode’ to
+	encoding ‘tocode’ into preallocated memory. Returns an error indicator
+	(0 or -1 with errno set). */
+#define iconv_open_into libiconv_open_into
+	extern LIBICONV_DLL_EXPORTED int iconv_open_into (const char* tocode, const char* fromcode,
+		iconv_allocation_t* resultp);
+
+	/* Control of attributes. */
+#define iconvctl libiconvctl
+	extern LIBICONV_DLL_EXPORTED int iconvctl (iconv_t cd, int request, void* argument);
+
+	/* Hook performed after every successful conversion of a Unicode character. */
+	typedef void (*iconv_unicode_char_hook) (unsigned int uc, void* data);
+	/* Hook performed after every successful conversion of a wide character. */
+	typedef void (*iconv_wide_char_hook) (wchar_t wc, void* data);
+	/* Set of hooks. */
+	struct iconv_hooks {
+		iconv_unicode_char_hook uc_hook;
+		iconv_wide_char_hook wc_hook;
+		void* data;
+	};
+
+	/* Fallback function.  Invoked when a small number of bytes could not be
+	converted to a Unicode character.  This function should process all
+	bytes from inbuf and may produce replacement Unicode characters by calling
+	the write_replacement callback repeatedly.  */
+	typedef void (*iconv_unicode_mb_to_uc_fallback)
+		(const char* inbuf, size_t inbufsize,
+		void (*write_replacement) (const unsigned int *buf, size_t buflen,
+		void* callback_arg),
+		void* callback_arg,
+		void* data);
+	/* Fallback function.  Invoked when a Unicode character could not be converted
+	to the target encoding.  This function should process the character and
+	may produce replacement bytes (in the target encoding) by calling the
+	write_replacement callback repeatedly.  */
+	typedef void (*iconv_unicode_uc_to_mb_fallback)
+		(unsigned int code,
+		void (*write_replacement) (const char *buf, size_t buflen,
+		void* callback_arg),
+		void* callback_arg,
+		void* data);
+#if HAVE_WCHAR_T
+	/* Fallback function.  Invoked when a number of bytes could not be converted to
+	a wide character.  This function should process all bytes from inbuf and may
+	produce replacement wide characters by calling the write_replacement
+	callback repeatedly.  */
+	typedef void (*iconv_wchar_mb_to_wc_fallback)
+		(const char* inbuf, size_t inbufsize,
+		void (*write_replacement) (const wchar_t *buf, size_t buflen,
+		void* callback_arg),
+		void* callback_arg,
+		void* data);
+	/* Fallback function.  Invoked when a wide character could not be converted to
+	the target encoding.  This function should process the character and may
+	produce replacement bytes (in the target encoding) by calling the
+	write_replacement callback repeatedly.  */
+	typedef void (*iconv_wchar_wc_to_mb_fallback)
+		(wchar_t code,
+		void (*write_replacement) (const char *buf, size_t buflen,
+		void* callback_arg),
+		void* callback_arg,
+		void* data);
+#else
+	/* If the wchar_t type does not exist, these two fallback functions are never
+	invoked.  Their argument list therefore does not matter.  */
+	typedef void (*iconv_wchar_mb_to_wc_fallback) ();
+	typedef void (*iconv_wchar_wc_to_mb_fallback) ();
+#endif
+	/* Set of fallbacks. */
+	struct iconv_fallbacks {
+		iconv_unicode_mb_to_uc_fallback mb_to_uc_fallback;
+		iconv_unicode_uc_to_mb_fallback uc_to_mb_fallback;
+		iconv_wchar_mb_to_wc_fallback mb_to_wc_fallback;
+		iconv_wchar_wc_to_mb_fallback wc_to_mb_fallback;
+		void* data;
+	};
+
+	/* Requests for iconvctl. */
+#define ICONV_TRIVIALP            0  /* int *argument */
+#define ICONV_GET_TRANSLITERATE   1  /* int *argument */
+#define ICONV_SET_TRANSLITERATE   2  /* const int *argument */
+#define ICONV_GET_DISCARD_ILSEQ   3  /* int *argument */
+#define ICONV_SET_DISCARD_ILSEQ   4  /* const int *argument */
+#define ICONV_SET_HOOKS           5  /* const struct iconv_hooks *argument */
+#define ICONV_SET_FALLBACKS       6  /* const struct iconv_fallbacks *argument */
+
+	/* Listing of locale independent encodings. */
+#define iconvlist libiconvlist
+	extern LIBICONV_DLL_EXPORTED void iconvlist (int (*do_one) (unsigned int namescount,
+		const char * const * names,
+		void* data),
+		void* data);
+
+	/* Canonicalize an encoding name.
+	The result is either a canonical encoding name, or name itself. */
+	extern LIBICONV_DLL_EXPORTED const char * iconv_canonicalize (const char * name);
+
+	/* Support for relocatable packages.  */
+
+	/* Sets the original and the current installation prefix of the package.
+	Relocation simply replaces a pathname starting with the original prefix
+	by the corresponding pathname with the current prefix instead.  Both
+	prefixes should be directory names without trailing slash (i.e. use ""
+	instead of "/").  */
+	extern LIBICONV_DLL_EXPORTED void libiconv_set_relocation_prefix (const char *orig_prefix,
+		const char *curr_prefix);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+#endif /* _LIBICONV_H */

+ 293 - 0
Burndiscs/BurndiscTest/iconv_impl.cpp

@@ -0,0 +1,293 @@
+#include "stdafx.h"
+#include "iconv.h"
+#include "iconv_impl.h"
+
+#ifdef USE_STATIC_ICONV // 使用静态库;
+// mt
+#if defined(_MT) && !defined(_DLL)	
+#ifdef _DEBUG// mtd;
+#pragma comment(lib,"./lib/libiconv_mtd.lib")
+#else // mt;
+#pragma comment(lib,"./lib/libiconv_mt.lib")
+#endif
+#endif
+
+// md;
+#if defined(_MT) && defined(_DLL)
+#ifdef _DEBUG // mdd;
+#pragma comment(lib,"./lib/libiconv_mdd.lib")
+#else // md;
+#pragma comment(lib,"./lib/libiconv_md.lib")
+#endif
+#endif
+#else	// 使用dll的静态连接;
+// mt
+#if defined(_MT) && !defined(_DLL)	
+#ifdef _DEBUG// mtd;
+#pragma comment(lib,"./dll/libiconv_mtd.lib")
+#else // mt;
+#pragma comment(lib,"./dll/libiconv_mt.lib")
+#endif
+#endif
+
+// md;
+#if defined(_MT) && defined(_DLL)
+#ifdef _DEBUG // mdd;
+#pragma comment(lib,"./dll/libiconv_mdd.lib")
+#else // md;
+#pragma comment(lib,"./dll/libiconv_md.lib")
+#endif
+#endif
+#endif
+
+/************************************************************************/
+/*  函数:[1/22/2018 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+std::string convert2(const char *from, const char* to, const char* inbuf, const size_t &inbufsize)
+{
+	int iconv_ret = 0;
+	// 打开字符集转换;
+	iconv_t hIconv = iconv_open(to, from);
+	if (-1 == (int)hIconv)
+		return "";//打开失败,可能不支持的字符集
+
+	size_t insize = inbufsize;
+	std::string strout;
+	// 循环利用;
+	size_t outsize = 512;
+	// 513多一位用做字符结束符;
+	char out[513] = { 0 };
+
+	while (insize > 0)
+	{
+		outsize = 512;
+		memset(out, 0, outsize);
+		// out地址保存不变,以便重复使用;
+		char *p = out;
+
+		// 开始转换;
+		iconv_ret = iconv(hIconv, (const char**)(&inbuf), &insize, &p, &outsize);
+		if (((iconv_ret == (size_t)-1) && (E2BIG == errno)) || (iconv_ret != (size_t)-1))
+		{
+			// out和p地址不同, p-out指针相减得到长度;
+			//strout.append(out, p - out);
+			strout.insert(strout.size(), out, p - out);
+		}
+	}
+
+	//关闭字符集转换
+	iconv_close(hIconv);
+
+	return strout;
+}
+
+std::string convert(const char *from, const char* to, const char* inbuf, const size_t &inbufsize)
+{
+	int iconv_ret = 0;
+	// 打开字符集转换;
+	iconv_t hIconv = iconv_open(to, from);
+	if (-1 == (int)hIconv)
+		return "";//打开失败,可能不支持的字符集
+
+	int status = 0;
+	int times = (inbufsize / 512) + 1;	// 预计可转换的次数;
+	iconv(hIconv, NULL, NULL, NULL, NULL);
+	size_t insize = inbufsize;
+	std::string strout = "";
+	// 循环利用;
+	size_t outsize = 512;
+	// 513多一位用做字符结束符;
+	char out[513] = { 0 };
+
+	while (insize > 0)
+	{
+		outsize = 512;
+		memset(out, 0, outsize);
+		// out地址保存不变,以便重复使用;
+		char *p = out;
+
+		// 开始转换;
+		//times--;
+		iconv_ret = iconv(hIconv, (const char**)(&inbuf), &insize, &p, &outsize);
+		if (out != p)
+		{
+			int saved_errno = errno;
+			strout.insert(strout.size(), out, p - out);
+			errno = saved_errno;
+		}
+
+		if (iconv_ret == (size_t)(-1))
+		{
+			if (errno == EILSEQ)
+			{//	输入中遇到无效的多字节序列;
+				int one = 1;
+				// 非法序列丢弃并继续;
+				iconvctl(hIconv, ICONV_SET_DISCARD_ILSEQ, &one);
+				status = -3;
+			}
+			else if (errno == EINVAL)
+			{// 输入中遇到了一个不完整的多字节序列;
+				if (inbufsize == 0)
+				{
+					status = -4;
+					goto done;
+				}
+				else
+				{
+					break;
+				}
+			}
+			else if (errno == E2BIG)
+			{// *outbuf没有足够的空间;
+				status = -5;
+				//goto done;
+			}
+			else {
+				status = -6;
+				goto done;
+			}
+		}
+		/*if (((iconv_ret == (size_t)-1) && (E2BIG == errno)) || (iconv_ret != (size_t)-1))
+		{
+		// out和p地址不同, p-out指针相减得到长度;
+		//strout.append(out, p - out);
+		strout.insert(strout.size(), out, p - out);
+		}*/
+	}
+
+done:
+	//关闭字符集转换
+	iconv_close(hIconv);
+
+	return strout;
+}
+
+/************************************************************************/
+/*  函数:[7/26/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+TString EnCode_UTF8URL(const TCHAR* pText)
+{
+	if (pText == NULL || pText[0] == '\0')
+		return _T("");
+
+	std::string tt = "";
+	std::string dd = "";
+	//ASCII2UTF8(pText, tt);
+#ifdef UNICODE 
+	tt = convert("UCS-2LE", "UTF-8", (char*)pText, _tcslen(pText) * sizeof(TCHAR));
+#else
+	tt = convert("ASCII", "UTF-8", pText, strlen(pText));
+#endif
+
+	size_t len = tt.length();
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)tt.at(i)))
+		{
+			char tempbuff[2] = { 0 };
+			sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+			dd.append(tempbuff);
+		}
+		else if (isspace((BYTE)tt.at(i)))
+		{
+			dd.append("+");
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+			dd.append(tempbuff);
+		}
+	}
+
+#ifdef UNICODE 
+	//tt = convert("ASCII", "UCS-2LE", dd.c_str(), dd.size());
+	//TString result;
+	//result.append((TCHAR*)tt.c_str(), dd.size());
+	//return result;
+	// 将以上4行代码,简化成一行;
+	return TString().append((TCHAR*)convert("ASCII", "UCS-2LE", dd.c_str(), dd.size()).c_str(), dd.size());
+#else
+	return dd;
+#endif
+
+}
+
+void EnCode_UTF8URL(const TCHAR* pText, TString& strResult)
+{
+	std::string tt = "";
+
+	//ASCII2UTF8(pText, tt);
+#ifdef UNICODE 
+	std::string result = "";
+	tt = convert("UCS-2LE", "UTF-8", (char*)pText, _tcslen(pText) * sizeof(TCHAR));
+#else
+	tt = convert("ASCII", "UTF-8", pText, strlen(pText));
+#endif
+
+	size_t len = tt.length();
+	for (size_t i = 0; i < len; i++)
+	{
+		if (isalnum((BYTE)tt.at(i)))
+		{
+			char tempbuff[2] = { 0 };
+			sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
+#ifdef UNICODE
+			result.append(tempbuff);
+#else
+			strResult.append(tempbuff);
+#endif
+		}
+		else if (isspace((BYTE)tt.at(i)))
+		{
+#ifdef UNICODE
+			result.append("+");
+#else
+			strResult.append("+");
+#endif
+		}
+		else
+		{
+			char tempbuff[4];
+			sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
+#ifdef UNICODE
+			result.append(tempbuff);
+#else
+			strResult.append(tempbuff);
+#endif
+		}
+	}
+
+#ifdef UNICODE 
+	//tt = convert("ASCII", "UCS-2LE", dd.c_str(), dd.size());
+	//TString result;
+	//result.append((TCHAR*)tt.c_str(), dd.size());
+	// 将以上代码,简化成一行;
+	strResult.append((TCHAR*)convert("ASCII", "UCS-2LE", result.c_str(), result.size()).c_str(), result.size());
+#endif
+}
+

+ 13 - 0
Burndiscs/BurndiscTest/iconv_impl.h

@@ -0,0 +1,13 @@
+#ifndef __ICONV_IMPL__
+#define __ICONV_IMPL__
+
+extern std::string convert2(const char *from, const char* to, const char* inbuf, const size_t &inbufsize);
+
+extern std::string convert(const char *from, const char* to, const char* inbuf, const size_t &inbufsize);
+
+extern TString EnCode_UTF8URL(IN const TCHAR* pText);
+
+extern void EnCode_UTF8URL(IN const TCHAR* pText, OUT TString& strResult);
+
+
+#endif

BIN
Burndiscs/BurndiscTest/lib/libiconv_md.lib


BIN
Burndiscs/BurndiscTest/lib/libiconv_mdd.lib


BIN
Burndiscs/BurndiscTest/lib/libiconv_mt.lib


BIN
Burndiscs/BurndiscTest/lib/libiconv_mtd.lib


BIN
Burndiscs/BurndiscTest/res/BurndiscTest.ico


+ 13 - 0
Burndiscs/BurndiscTest/res/BurndiscTest.rc2

@@ -0,0 +1,13 @@
+//
+// BurndiscTest.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 119 - 0
Burndiscs/BurndiscTest/stdafx.cpp

@@ -0,0 +1,119 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// BurndiscTest.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+BOOL NERO_CALLBACK_ATTR _IdleCallback (void *pUserData)
+{
+
+	return false;
+}
+
+NeroUserDlgInOut NERO_CALLBACK_ATTR _UserDialog (void *pUserData, NeroUserDlgInOut type, void *data)
+{
+	return DLG_RETURN_EXIT;
+}
+
+BOOL NERO_CALLBACK_ATTR _ProgressCallback (void *pUserData, DWORD dwProgressInPercent)
+{
+	printf ("%03d%%\r", dwProgressInPercent);
+
+	return false;
+}
+
+BOOL NERO_CALLBACK_ATTR _AbortedCallback (void *pUserData)
+{
+	//	printf("Abort ?\n");
+
+	return false;
+}
+
+void NERO_CALLBACK_ATTR _AddLogLine (void *pUserData, NERO_TEXT_TYPE type, const char *text)
+{
+	char *header = "  ";
+	const char *start;
+
+	switch (type) {
+	case NERO_TEXT_INFO:        /* informative text                     */
+		header = "i ";
+		break;
+	case NERO_TEXT_STOP:        /* some operation stopped prematurely   */
+		header = "# ";
+		break;
+	case NERO_TEXT_EXCLAMATION: /* important information                */
+		header = "! ";
+		break;
+	case NERO_TEXT_QUESTION:    /* a question which requires an answer  */
+		header = "? ";
+		break;
+	case NERO_TEXT_DRIVE:		/* a message concerning a CD-ROM drive or recorder */
+		header = "- ";
+		break;
+	default:
+		break;
+	}
+
+	start = text;
+	while (start) {
+		const char *end = strchr (start, '\n');
+		int len = end ? (int)(end - start) : strlen (start);
+
+		fputs (header, stdout);
+		fwrite (start, 1, len, stdout);
+		// clear rest of line
+		len = 79 - strlen (header) - len;
+		while (--len >= 0) {
+			putchar (' ');
+		}
+
+		puts ("");
+
+		start = end ? end + 1 : NULL;
+	}
+}
+
+void NERO_CALLBACK_ATTR _SetPhaseCallback (void *pUserData, const char *text)
+{
+	int len;
+
+	printf ("     %s", text);
+	// clear rest of line
+	len = 79 - strlen (text) - 5;
+	while (--len >= 0) {
+		putchar (' ');
+	}
+	putchar ('\r');
+}
+
+void NERO_CALLBACK_ATTR _DisableAbortCallback (void *pUserData, BOOL enableAbort)
+{
+	if (!enableAbort)
+		puts("The current process cannot be interrupted");
+	else puts("The process can be interrupted again");
+}
+
+void NERO_CALLBACK_ATTR _SetMajorPhaseCallback(void *pUserData,NERO_MAJOR_PHASE phase,void *reserved)
+{
+}
+
+DWORD NERO_CALLBACK_ATTR _WriteIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen)
+{
+	return fwrite (pBuffer, 1, dwLen, (FILE *)pUserData);
+}
+
+BOOL NERO_CALLBACK_ATTR _EOFCallback (void *pUserData)
+{
+	return feof ((FILE *)pUserData);
+}
+
+BOOL NERO_CALLBACK_ATTR _ErrorCallback (void *pUserData)
+{
+	return ferror ((FILE *)pUserData);
+}
+
+DWORD NERO_CALLBACK_ATTR _ReadIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen)
+{
+	return fread (pBuffer, 1, dwLen, (FILE *)pUserData);
+}

+ 178 - 0
Burndiscs/BurndiscTest/stdafx.h

@@ -0,0 +1,178 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+#ifdef USE_STATIC_ICONV // 使用静态库;
+#ifndef LIBICONV_EXPORTS
+#define LIBICONV_EXPORTS 1
+#endif
+
+#ifndef BUILDING_LIBICONV
+#define BUILDING_LIBICONV 1
+#endif
+
+#ifndef BUILDING_LIBCHARSET
+#define BUILDING_LIBCHARSET 1
+#endif
+#endif
+
+#include <vector>
+#include <string>
+using namespace std;
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+#include "iconv_impl.h"
+#include "filehelp.h"
+
+#ifdef _DEBUG
+#include "..\Burndiscs\NeroBurndisc.h"
+#include "..\Burndiscs\NeroDevice.h"
+#include "..\Burndiscs\NeroMedia.h"
+#include "..\Burndiscs\NeroItem.h"
+#include "..\Burndiscs\IBurndisc.h"
+#include "..\Burndiscs\NeroImpl.h"
+
+#include <imapi2.h>
+#include "..\Burndiscs\DiscFormatData.h"
+#include "..\Burndiscs\DiscFormatDataEvent.h"
+#include "..\Burndiscs\DiscMaster.h"
+#include "..\Burndiscs\DiscRecorder.h"
+#include "..\Burndiscs\IMAPI2Impl.h"
+#endif
+
+#include <shlwapi.h>        // for SHCreateStreamOnFileEx
+// /* for the settings */
+// static BOOL NERO_CALLBACK_ATTR IdleCallback (void *pUserData);
+// static NeroUserDlgInOut NERO_CALLBACK_ATTR UserDialog (void *pUserData, NeroUserDlgInOut type, void *data);
+// 
+// /* for the progress display */
+// static BOOL NERO_CALLBACK_ATTR ProgressCallback (void *pUserData, DWORD dwProgressInPercent);
+// static BOOL NERO_CALLBACK_ATTR AbortedCallback (void *pUserData);
+// static void NERO_CALLBACK_ATTR AddLogLine (void *pUserData, NERO_TEXT_TYPE type, const char *text);
+// static void NERO_CALLBACK_ATTR SetPhaseCallback (void *pUserData, const char *text);
+// static void NERO_CALLBACK_ATTR DisableAbortCallback (void *pUserData,BOOL abortEnabled);
+// static void NERO_CALLBACK_ATTR SetMajorPhaseCallback(void *pUserData,NERO_MAJOR_PHASE phase,void *reserved);
+// 
+// /* IO callbacks - both take a FILE * as user data */
+// static DWORD NERO_CALLBACK_ATTR WriteIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen);
+// static DWORD NERO_CALLBACK_ATTR ReadIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen);
+// static BOOL NERO_CALLBACK_ATTR EOFCallback (void *pUserData);
+// static BOOL NERO_CALLBACK_ATTR ErrorCallback (void *pUserData);
+extern BOOL NERO_CALLBACK_ATTR _IdleCallback(void *pUserData);
+extern NeroUserDlgInOut NERO_CALLBACK_ATTR _UserDialog(void *pUserData, NeroUserDlgInOut type, void *data);
+extern BOOL NERO_CALLBACK_ATTR _ProgressCallback(void *pUserData, DWORD dwProgressInPercent);
+extern BOOL NERO_CALLBACK_ATTR _AbortedCallback(void *pUserData);
+extern void NERO_CALLBACK_ATTR _AddLogLine(void *pUserData, NERO_TEXT_TYPE type, const char *text);
+extern void NERO_CALLBACK_ATTR _SetPhaseCallback(void *pUserData, const char *text);
+extern void NERO_CALLBACK_ATTR _DisableAbortCallback(void *pUserData, BOOL enableAbort);
+extern void NERO_CALLBACK_ATTR _SetMajorPhaseCallback(void *pUserData, NERO_MAJOR_PHASE phase, void *reserved);
+extern DWORD NERO_CALLBACK_ATTR _WriteIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+extern BOOL NERO_CALLBACK_ATTR _EOFCallback(void *pUserData);
+extern BOOL NERO_CALLBACK_ATTR _ErrorCallback(void *pUserData);
+extern DWORD NERO_CALLBACK_ATTR _ReadIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+
+
+///删除一个数组指针的宏定义
+#ifndef DELETEA
+#define DELETEA(ptr) \
+if(NULL != ptr) \
+{ \
+	delete[] ptr; \
+	ptr = NULL; \
+}
+#endif
+
+// 删除一个指针的宏定义;
+#ifndef FREEP
+#define FREEP(ptr)		\
+if(NULL != ptr)		\
+{					\
+	free(ptr) ;		\
+	ptr = NULL;		\
+}
+#endif
+
+//删除一个指针的宏定义;
+#ifndef DELETEP
+#define DELETEP(ptr)	\
+if(NULL != (ptr))	\
+{					\
+	delete (ptr);	\
+	(ptr) = NULL;	\
+}
+#endif
+
+// 删除一个GDI对象的宏定义;
+#define DELETEOBJECT(ptr)	\
+if(NULL != (ptr))		\
+{						\
+	::DeleteObject (ptr);\
+	(ptr) = NULL;		\
+}
+
+// Destroy一个Window;
+#define DESTROYWINDOW(hWnd)	\
+if (IsWindow(hWnd))		\
+{ \
+	DestroyWindow(hWnd); \
+}
+
+#define  RELEASEP(ptr)\
+if ( ptr)\
+{\
+	ptr->Release();\
+	ptr = NULL;\
+}
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+

+ 26 - 0
Burndiscs/BurndiscTest/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+

+ 120 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.cpp

@@ -0,0 +1,120 @@
+
+// BurndiscTest2.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "BurndiscTest2.h"
+#include "BurndiscTest2Dlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CBurndiscTest2App
+
+BEGIN_MESSAGE_MAP(CBurndiscTest2App, CWinAppEx)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CBurndiscTest2App 构造
+
+CBurndiscTest2App::CBurndiscTest2App()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CBurndiscTest2App 对象
+
+CBurndiscTest2App theApp;
+
+
+// CBurndiscTest2App 初始化
+
+BOOL CBurndiscTest2App::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+	AfxEnableControlContainer();
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+#if 1 // 测试刻录接口;
+
+	//_CrtSetBreakAlloc(202); //98500为上面内存泄漏的块号.
+	bool IsNero = true;
+	if (LoadIBurndiscLibrary(IsNero))
+	{
+		if (IsNero)
+		{
+			g_IBurndisc->NeroCallback(
+				NULL,
+				_IdleCallback,
+				_UserDialog,
+				_ProgressCallback,
+				NULL,
+				_AbortedCallback,
+				_AddLogLine,
+				_SetPhaseCallback,
+				_DisableAbortCallback,
+				_SetMajorPhaseCallback,
+				_WriteIOCallback,
+				_ReadIOCallback,
+				_EOFCallback,
+				_ErrorCallback
+			);
+		}
+		else
+		{
+			g_IBurndisc->IMAPI2Set(NULL);
+		}
+
+		if (g_IBurndisc->Initialize())
+		{
+			g_IBurndisc->GetAvailableDrives();
+			g_IBurndisc->AddFolder2Disc(_T("IBurndisc4"), _T("E:\\测试相片"));
+			g_IBurndisc->BurnMedia(0, _T(""), _T(""));
+		}
+	}
+
+	FreeIBurndiscLibrary();
+
+#endif
+
+	CBurndiscTest2Dlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}

+ 32 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.h

@@ -0,0 +1,32 @@
+
+// BurndiscTest2.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CBurndiscTest2App:
+// 有关此类的实现,请参阅 BurndiscTest2.cpp
+//
+
+class CBurndiscTest2App : public CWinAppEx
+{
+public:
+	CBurndiscTest2App();
+
+// 重写
+	public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CBurndiscTest2App theApp;

+ 197 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.rc

@@ -0,0 +1,197 @@
+// Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+	"#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+    "LANGUAGE 4, 2\r\n"
+    "#pragma code_page(936)\r\n"
+    "#include ""res\\BurndiscTest2.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+    "#include ""l.CHS\\afxres.rc""  	// 标准组件\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 图标
+//
+
+// ID 值最低的图标放在最前面,以确保应用程序图标
+// 在所有系统中保持一致。
+IDR_MAINFRAME           ICON         "res\\BurndiscTest2.ico"
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 对话框
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "关于 BurndiscTest2"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
+    LTEXT           "BurndiscTest2,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2018",IDC_STATIC,42,26,114,8
+    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
+END
+
+IDD_BURNDISCTEST2_DIALOG DIALOGEX  0, 0, 320, 200
+STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION
+ | DS_MODALFRAME
+ | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "BurndiscTest2"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    DEFPUSHBUTTON   "确定",IDOK,209,179,50,14
+    PUSHBUTTON      "取消",IDCANCEL,263,179,50,14
+	CTEXT           "TODO: 在此放置对话框控件。",IDC_STATIC,10,96,300,8
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 版本
+//
+
+VS_VERSION_INFO     VERSIONINFO
+  FILEVERSION       1,0,0,1
+  PRODUCTVERSION    1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+        BLOCK "080403a8"
+		BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+			VALUE "FileVersion",     "1.0.0.1"
+			VALUE "InternalName",    "BurndiscTest2.exe"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+			VALUE "OriginalFilename","BurndiscTest2.exe"
+            VALUE "ProductName", "TODO: <产品名>"
+			VALUE "ProductVersion",  "1.0.0.1"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x0804, 936
+    END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 163
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 55
+    END
+    IDD_BURNDISCTEST2_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 313
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 193
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+    IDS_ABOUTBOX            "关于 BurndiscTest2(&A)..."
+END
+
+
+#endif
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\\BurndiscTest2.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#include "l.CHS\\afxres.rc"  	// 标准组件
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED
+

+ 270 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.vcproj

@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="BurndiscTest2"
+	ProjectGUID="{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}"
+	RootNamespace="BurndiscTest2"
+	Keyword="MFCProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\Burndiscs\Nero\Include"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="..\Burndiscs\Nero\Include"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+				MinimalRebuild="false"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\BurndiscTest2.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTest2Dlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\BurndiscTest2.h"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTest2Dlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\res\BurndiscTest2.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\BurndiscTest2.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\BurndiscTest2.rc2"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 145 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.vcxproj

@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}</ProjectGuid>
+    <RootNamespace>BurndiscTest2</RootNamespace>
+    <Keyword>MFCProj</Keyword>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>15.0.27428.2015</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(ProjectName)\$(Configuration)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(ProjectName)\$(Configuration)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <AdditionalIncludeDirectories>..\Burndiscs\Nero\Include</AdditionalIncludeDirectories>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>false</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <AdditionalIncludeDirectories>..\Burndiscs\Nero\Include</AdditionalIncludeDirectories>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="BurndiscTest2.cpp" />
+    <ClCompile Include="BurndiscTest2Dlg.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="BurndiscTest2.h" />
+    <ClInclude Include="BurndiscTest2Dlg.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\BurndiscTest2.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BurndiscTest2.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BurndiscTest2.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 63 - 0
Burndiscs/BurndiscTest2/BurndiscTest2.vcxproj.filters

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="BurndiscTest2.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="BurndiscTest2Dlg.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="BurndiscTest2.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="BurndiscTest2Dlg.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\BurndiscTest2.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="BurndiscTest2.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\BurndiscTest2.rc2">
+      <Filter>资源文件</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+</Project>

+ 153 - 0
Burndiscs/BurndiscTest2/BurndiscTest2Dlg.cpp

@@ -0,0 +1,153 @@
+
+// BurndiscTest2Dlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "BurndiscTest2.h"
+#include "BurndiscTest2Dlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+	enum { IDD = IDD_ABOUTBOX };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+END_MESSAGE_MAP()
+
+
+// CBurndiscTest2Dlg 对话框
+
+
+
+
+CBurndiscTest2Dlg::CBurndiscTest2Dlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CBurndiscTest2Dlg::IDD, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CBurndiscTest2Dlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CBurndiscTest2Dlg, CDialog)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+// CBurndiscTest2Dlg 消息处理程序
+
+BOOL CBurndiscTest2Dlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CBurndiscTest2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CBurndiscTest2Dlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CBurndiscTest2Dlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+

+ 32 - 0
Burndiscs/BurndiscTest2/BurndiscTest2Dlg.h

@@ -0,0 +1,32 @@
+
+// BurndiscTest2Dlg.h : 头文件
+//
+
+#pragma once
+
+
+// CBurndiscTest2Dlg 对话框
+class CBurndiscTest2Dlg : public CDialog
+{
+// 构造
+public:
+	CBurndiscTest2Dlg(CWnd* pParent = NULL);	// 标准构造函数
+
+// 对话框数据
+	enum { IDD = IDD_BURNDISCTEST2_DIALOG };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+};

+ 101 - 0
Burndiscs/BurndiscTest2/IBurndisc.h

@@ -0,0 +1,101 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __I_BURN_DISC__
+#define __I_BURN_DISC__
+
+#pragma once
+
+#include "Nero.h"
+
+typedef struct __DEVINFO__
+{
+	int				nIndex;					// 设备索引;
+	TString			strDevName;				// 设备名称;
+	TString			strDevUId;				// 设备的id;
+	void*			pDevInfo;				// 设备对象;
+
+	__DEVINFO__() :nIndex(-1), pDevInfo(NULL) {	}
+}DeviceInfo, *pDeviceInfo;
+
+// {96D4FD2E-115A-474d-A5E0-D1400D14083B}
+static const GUID IID_IBurndisc =
+{ 0x96d4fd2e, 0x115a, 0x474d,{ 0xa5, 0xe0, 0xd1, 0x40, 0xd, 0x14, 0x8, 0x3b } };
+
+interface IBurndisc :public IUnknown
+{
+public:
+	// 初始化刻录环境;
+	virtual bool Initialize() = 0;
+
+	// 获取可用的设备数量;
+	virtual int GetAvailableDrives() = 0;
+
+	// 获取刻录机设备信息;
+	virtual void* GetDeivceInfo(int nIndex) = 0;
+	virtual void* GetDeivceInfo(const TCHAR *pszDevName) = 0;
+
+	// 添加文件或文件夹;
+	virtual void AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles) = 0;
+	virtual void AddFolder2Disc(TString strFatherNode, TString strFolder) = 0;
+	/*
+	// 获取媒体光盘的信息;
+	virtual void* GetMediaInfo(int nIndex) = 0;
+	virtual void* GetMediaInfo(const TCHAR *pszDevName) = 0;
+	virtual void* GetMediaInfo(void *pDevInfo) = 0;
+
+	// 获取设备的刻录速度;
+	virtual bool GetWriteSpeeds() = 0;
+
+	// 获取擦除设备的时长;
+	virtual bool GetCDRWErasingTime() = 0;
+
+	// 弹出或加载CD;
+	virtual bool EjectLoadCD() = 0;
+	*/
+	virtual void 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
+	) = 0;
+
+	virtual void IMAPI2Set(void* pDailog) = 0;
+
+	// 设置写速度;
+	virtual bool SetWriteSpeed(ULONG nIndex) = 0;
+
+	// 擦除设备;
+	virtual void EraseMedia(int nIndex) = 0;
+
+	// 写光盘;
+	virtual bool BurnMedia(int nIndex, TString strArtist, TString strTitle) = 0;
+
+};
+
+
+#endif

+ 27 - 0
Burndiscs/BurndiscTest2/Nero.h

@@ -0,0 +1,27 @@
+#ifndef __NERO__
+#define __NERO__
+
+#include "NeroAPIGlue.h"
+#define NERO_WAITCD_TEXTS
+#include "NeroUserDialog.h"
+#undef NERO_WAITCD_TEXTS
+
+/* for the settings */
+typedef BOOL(NERO_CALLBACK_ATTR *IdleCallback) (void *pUserData);
+typedef NeroUserDlgInOut(NERO_CALLBACK_ATTR *UserDialog)(void *pUserData, NeroUserDlgInOut type, void *data);
+
+/* for the progress display */
+typedef BOOL(NERO_CALLBACK_ATTR *ProgressCallback) (void *pUserData, DWORD dwProgressInPercent);
+typedef BOOL(NERO_CALLBACK_ATTR *AbortedCallback)(void *pUserData);
+typedef void (NERO_CALLBACK_ATTR *AddLogLine)(void *pUserData, NERO_TEXT_TYPE type, const char *text);
+typedef void (NERO_CALLBACK_ATTR *SetPhaseCallback)(void *pUserData, const char *text);
+typedef void (NERO_CALLBACK_ATTR *DisableAbortCallback)(void *pUserData, BOOL abortEnabled);
+typedef void (NERO_CALLBACK_ATTR *SetMajorPhaseCallback)(void *pUserData, NERO_MAJOR_PHASE phase, void *reserved);
+
+/* IO callbacks - both take a FILE * as user data */
+typedef DWORD(NERO_CALLBACK_ATTR *WriteIOCallback)(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+typedef DWORD(NERO_CALLBACK_ATTR *ReadIOCallback)(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+typedef BOOL(NERO_CALLBACK_ATTR  *EOFCallback)(void *pUserData);
+typedef BOOL(NERO_CALLBACK_ATTR  *ErrorCallback)(void *pUserData);
+
+#endif

+ 69 - 0
Burndiscs/BurndiscTest2/ReadMe.txt

@@ -0,0 +1,69 @@
+================================================================================
+    MICROSOFT 基础类库: BurndiscTest2 项目概述
+===============================================================================
+
+应用程序向导已为您创建此 BurndiscTest2 应用程序。此应用程序不仅演示使用 Microsoft 基础类的基本知识,而且可作为编写应用程序的起点。
+
+此文件包含组成 BurndiscTest2 应用程序的各个文件的内容摘要。
+
+BurndiscTest2.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件。
+    它包含有关生成文件的 Visual C++ 版本的信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+BurndiscTest2.h
+    这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CBurndiscTest2App 应用程序类。
+
+BurndiscTest2.cpp
+    这是包含应用程序类 CBurndiscTest2App 的主要应用程序源文件。
+
+BurndiscTest2.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
+
+res\BurndiscTest2.ico
+    这是用作应用程序图标的图标文件。此图标包括在主要资源文件 BurndiscTest2.rc 中。
+
+res\BurndiscTest2.rc2
+    此文件包含不是由 Microsoft Visual C++ 编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+应用程序向导创建一个对话框类:
+
+BurndiscTest2Dlg.h,BurndiscTest2Dlg.cpp - 对话框
+    这些文件包含 CBurndiscTest2Dlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 BurndiscTest2.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他功能:
+
+ActiveX 控件
+    应用程序包括对使用 ActiveX 控件的支持。
+
+打印及打印预览支持
+    应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 BurndiscTest2.pch 的预编译头(PCH)文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,它定义新资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+BurndiscTest2.manifest
+	Windows XP 使用应用程序清单文件描述应用程序	对特定版本并行程序集的依赖性。加载程序使用此	信息从程序集缓存加载相应程序集或	从应用程序加载私有信息。应用程序清单可能作为	与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件包括在内以便重新发布,	也可能以资源的形式包括在该可执行文件中。
+/////////////////////////////////////////////////////////////////////////////
+
+其他注释:
+
+应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
+
+如果应用程序在共享 DLL 中使用 MFC,则将需要重新发布 MFC DLL。如果应用程序所用与操作系统的区域设置不同,则也将必须重新发布对应的本地化资源 MFC90XXX.DLL。
+有关这两个主题的详细信息,请参阅 MSDN 文档中有关重新发布 Visual C++ 应用程序的部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 21 - 0
Burndiscs/BurndiscTest2/Resource.h

@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by BurndiscTest2.rc
+//
+#define IDR_MAINFRAME					128
+#define IDM_ABOUTBOX					0x0010
+#define IDD_ABOUTBOX					100
+#define IDS_ABOUTBOX					101
+#define IDD_BURNDISCTEST2_DIALOG				102
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE	129
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#define _APS_NEXT_COMMAND_VALUE		32771
+#endif
+#endif

BIN
Burndiscs/BurndiscTest2/res/BurndiscTest2.ico


+ 13 - 0
Burndiscs/BurndiscTest2/res/BurndiscTest2.rc2

@@ -0,0 +1,13 @@
+//
+// BurndiscTest2.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 178 - 0
Burndiscs/BurndiscTest2/stdafx.cpp

@@ -0,0 +1,178 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// BurndiscTest2.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+HMODULE g_hBurdisc = NULL;
+IBurndisc* g_IBurndisc = NULL;
+/************************************************************************/
+/*  函数:[4/1/2018 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool LoadIBurndiscLibrary(bool IsNeroModel)
+{
+	g_hBurdisc = (HMODULE)LoadLibrary(_T("Burndiscs.dll"));
+	if (g_hBurdisc)
+	{
+		ICreateIBurndisc pCreateBurndisc = (ICreateIBurndisc)GetProcAddress(g_hBurdisc, "CreateIBurndisc");
+		if (pCreateBurndisc)
+		{
+			g_IBurndisc = pCreateBurndisc(IsNeroModel);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/************************************************************************/
+/*  函数:[4/1/2018 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void FreeIBurndiscLibrary()
+{
+	if (g_IBurndisc)
+		g_IBurndisc->Release();
+	g_IBurndisc = NULL;
+
+	if (g_hBurdisc)
+		FreeLibrary(g_hBurdisc);
+}
+
+
+BOOL NERO_CALLBACK_ATTR _IdleCallback(void *pUserData)
+{
+
+	return false;
+}
+
+NeroUserDlgInOut NERO_CALLBACK_ATTR _UserDialog(void *pUserData, NeroUserDlgInOut type, void *data)
+{
+	return DLG_RETURN_EXIT;
+}
+
+BOOL NERO_CALLBACK_ATTR _ProgressCallback(void *pUserData, DWORD dwProgressInPercent)
+{
+	printf("%03d%%\r", dwProgressInPercent);
+
+	return false;
+}
+
+BOOL NERO_CALLBACK_ATTR _AbortedCallback(void *pUserData)
+{
+	//	printf("Abort ?\n");
+
+	return false;
+}
+
+void NERO_CALLBACK_ATTR _AddLogLine(void *pUserData, NERO_TEXT_TYPE type, const char *text)
+{
+	char *header = "  ";
+	const char *start;
+
+	switch (type) {
+	case NERO_TEXT_INFO:        /* informative text                     */
+		header = "i ";
+		break;
+	case NERO_TEXT_STOP:        /* some operation stopped prematurely   */
+		header = "# ";
+		break;
+	case NERO_TEXT_EXCLAMATION: /* important information                */
+		header = "! ";
+		break;
+	case NERO_TEXT_QUESTION:    /* a question which requires an answer  */
+		header = "? ";
+		break;
+	case NERO_TEXT_DRIVE:		/* a message concerning a CD-ROM drive or recorder */
+		header = "- ";
+		break;
+	default:
+		break;
+	}
+
+	start = text;
+	while (start) {
+		const char *end = strchr(start, '\n');
+		int len = end ? (int)(end - start) : strlen(start);
+
+		fputs(header, stdout);
+		fwrite(start, 1, len, stdout);
+		// clear rest of line
+		len = 79 - strlen(header) - len;
+		while (--len >= 0) {
+			putchar(' ');
+		}
+
+		puts("");
+
+		start = end ? end + 1 : NULL;
+	}
+}
+
+void NERO_CALLBACK_ATTR _SetPhaseCallback(void *pUserData, const char *text)
+{
+	int len;
+
+	printf("     %s", text);
+	// clear rest of line
+	len = 79 - strlen(text) - 5;
+	while (--len >= 0) {
+		putchar(' ');
+	}
+	putchar('\r');
+}
+
+void NERO_CALLBACK_ATTR _DisableAbortCallback(void *pUserData, BOOL enableAbort)
+{
+	if (!enableAbort)
+		puts("The current process cannot be interrupted");
+	else puts("The process can be interrupted again");
+}
+
+void NERO_CALLBACK_ATTR _SetMajorPhaseCallback(void *pUserData, NERO_MAJOR_PHASE phase, void *reserved)
+{
+}
+
+DWORD NERO_CALLBACK_ATTR _WriteIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen)
+{
+	return fwrite(pBuffer, 1, dwLen, (FILE *)pUserData);
+}
+
+BOOL NERO_CALLBACK_ATTR _EOFCallback(void *pUserData)
+{
+	return feof((FILE *)pUserData);
+}
+
+BOOL NERO_CALLBACK_ATTR _ErrorCallback(void *pUserData)
+{
+	return ferror((FILE *)pUserData);
+}
+
+DWORD NERO_CALLBACK_ATTR _ReadIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen)
+{
+	return fread(pBuffer, 1, dwLen, (FILE *)pUserData);
+}

+ 92 - 0
Burndiscs/BurndiscTest2/stdafx.h

@@ -0,0 +1,92 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+#include "Nero.h"
+#include "IBurndisc.h"
+
+typedef IBurndisc* (WINAPI *ICreateIBurndisc)(bool IsNeroModel);
+extern IBurndisc* g_IBurndisc;
+extern bool LoadIBurndiscLibrary(bool IsNeroModel = true);
+extern void FreeIBurndiscLibrary();
+
+extern BOOL NERO_CALLBACK_ATTR _IdleCallback(void *pUserData);
+extern NeroUserDlgInOut NERO_CALLBACK_ATTR _UserDialog(void *pUserData, NeroUserDlgInOut type, void *data);
+extern BOOL NERO_CALLBACK_ATTR _ProgressCallback(void *pUserData, DWORD dwProgressInPercent);
+// extern BOOL NERO_CALLBACK_ATTR _ProgressCallback(void *pUserData, DWORD dwProgressInPercent);
+extern BOOL NERO_CALLBACK_ATTR _AbortedCallback(void *pUserData);
+extern void NERO_CALLBACK_ATTR _AddLogLine(void *pUserData, NERO_TEXT_TYPE type, const char *text);
+extern void NERO_CALLBACK_ATTR _SetPhaseCallback(void *pUserData, const char *text);
+extern void NERO_CALLBACK_ATTR _DisableAbortCallback(void *pUserData, BOOL enableAbort);
+extern void NERO_CALLBACK_ATTR _SetMajorPhaseCallback(void *pUserData, NERO_MAJOR_PHASE phase, void *reserved);
+extern DWORD NERO_CALLBACK_ATTR _WriteIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+extern DWORD NERO_CALLBACK_ATTR _ReadIOCallback(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+extern BOOL NERO_CALLBACK_ATTR _EOFCallback(void *pUserData);
+extern BOOL NERO_CALLBACK_ATTR _ErrorCallback(void *pUserData);
+
+

+ 26 - 0
Burndiscs/BurndiscTest2/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+

+ 36 - 0
Burndiscs/Burndiscs - 17.sln

@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27428.2015
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Burndiscs", "Burndiscs\Burndiscs.vcxproj", "{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BurndiscTest", "BurndiscTest\BurndiscTest.vcxproj", "{40158659-BABD-4316-9F9F-9771E5228126}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BurndiscTest2", "BurndiscTest2\BurndiscTest2.vcxproj", "{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Debug|Win32.Build.0 = Debug|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Release|Win32.ActiveCfg = Release|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Release|Win32.Build.0 = Release|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Debug|Win32.ActiveCfg = Debug|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Release|Win32.ActiveCfg = Release|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Release|Win32.Build.0 = Release|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Debug|Win32.Build.0 = Debug|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Release|Win32.ActiveCfg = Release|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {051A6DF0-F255-4C21-9DF1-B24EED5DC438}
+	EndGlobalSection
+EndGlobal

+ 31 - 0
Burndiscs/Burndiscs.sln

@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Burndiscs", "Burndiscs\Burndiscs.vcproj", "{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BurndiscTest", "BurndiscTest\BurndiscTest.vcproj", "{40158659-BABD-4316-9F9F-9771E5228126}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BurndiscTest2", "BurndiscTest2\BurndiscTest2.vcproj", "{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Debug|Win32.Build.0 = Debug|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Release|Win32.ActiveCfg = Release|Win32
+		{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}.Release|Win32.Build.0 = Release|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Debug|Win32.ActiveCfg = Debug|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Release|Win32.ActiveCfg = Release|Win32
+		{40158659-BABD-4316-9F9F-9771E5228126}.Release|Win32.Build.0 = Release|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Debug|Win32.Build.0 = Debug|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Release|Win32.ActiveCfg = Release|Win32
+		{7EF00B5F-AD1C-4C63-8C73-E912B245B0C9}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 95 - 0
Burndiscs/Burndiscs/Burndiscs.cpp

@@ -0,0 +1,95 @@
+// Burndiscs.cpp : 定义 DLL 的初始化例程。
+//
+
+#include "stdafx.h"
+#include "Burndiscs.h"
+#include "IBurndisc.h"
+#include "NeroImpl.h"
+#include "IMAPI2Impl.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+//
+//TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
+//		则从此 DLL 导出的任何调入
+//		MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
+//		该函数的最前面。
+//
+//		例如:
+//
+//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
+//		{
+//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
+//			// 此处为普通函数体
+//		}
+//
+//		此宏先于任何 MFC 调用
+//		出现在每个函数中十分重要。这意味着
+//		它必须作为函数中的第一个语句
+//		出现,甚至先于所有对象变量声明,
+//		这是因为它们的构造函数可能生成 MFC
+//		DLL 调用。
+//
+//		有关其他详细信息,
+//		请参阅 MFC 技术说明 33 和 58。
+//
+
+// CBurndiscsApp
+
+BEGIN_MESSAGE_MAP(CBurndiscsApp, CWinApp)
+END_MESSAGE_MAP()
+
+
+// CBurndiscsApp 构造
+
+CBurndiscsApp::CBurndiscsApp()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CBurndiscsApp 对象
+
+CBurndiscsApp theApp;
+
+
+// CBurndiscsApp 初始化
+
+BOOL CBurndiscsApp::InitInstance()
+{
+	CWinApp::InitInstance();
+
+	return TRUE;
+}
+
+/************************************************************************/
+/*  函数:[4/1/2018 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+extern "C" IBurndisc* PASCAL EXPORT CreateIBurndisc(bool IsNeroMode)
+{
+	AFX_MANAGE_STATE(AfxGetStaticModuleState());
+	// 此处为普通函数体
+	IBurndisc *pBurdisc = NULL;
+	if ( IsNeroMode )
+		pBurdisc = new CNeroImpl();
+	else
+		pBurdisc = new CIMAPI2Impl();
+	pBurdisc->AddRef();
+
+	return pBurdisc;
+}

+ 7 - 0
Burndiscs/Burndiscs/Burndiscs.def

@@ -0,0 +1,7 @@
+; Burndiscs.def : 声明 DLL 的模块参数。
+
+LIBRARY      "Burndiscs"
+
+EXPORTS
+    ; 此处可以是显式导出
+	CreateIBurndisc

+ 27 - 0
Burndiscs/Burndiscs/Burndiscs.h

@@ -0,0 +1,27 @@
+// Burndiscs.h : Burndiscs DLL 的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CBurndiscsApp
+// 有关此类实现的信息,请参阅 Burndiscs.cpp
+//
+
+class CBurndiscsApp : public CWinApp
+{
+public:
+	CBurndiscsApp();
+
+// 重写
+public:
+	virtual BOOL InitInstance();
+
+	DECLARE_MESSAGE_MAP()
+};

+ 125 - 0
Burndiscs/Burndiscs/Burndiscs.rc

@@ -0,0 +1,125 @@
+// Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+	"#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+	"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+	"LANGUAGE 4, 2\r\n"
+	"#pragma code_page(936)\r\n"
+    "#include ""res\\Burndiscs.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+#ifndef _AFXDLL
+    "#include ""l.CHS\\afxres.rc""  	// 标准组件\r\n"
+#endif
+    "#endif\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 版本
+//
+
+VS_VERSION_INFO     VERSIONINFO
+  FILEVERSION       1,0,0,1
+  PRODUCTVERSION    1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+        BLOCK "080403a8"
+		BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+			VALUE "FileVersion",     "1.0.0.1"
+			VALUE "InternalName",    "Burndiscs.dll"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+			VALUE "OriginalFilename","Burndiscs.dll"
+            VALUE "ProductName", "TODO: <产品名>"
+			VALUE "ProductVersion",  "1.0.0.1"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x0804, 936
+    END
+END
+
+#endif
+#ifndef APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\\Burndiscs.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#ifndef _AFXDLL
+#include "l.CHS\\afxres.rc"  	// 标准组件
+#endif
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED
+

+ 381 - 0
Burndiscs/Burndiscs/Burndiscs.vcproj

@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="Burndiscs"
+	ProjectGUID="{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}"
+	RootNamespace="Burndiscs"
+	Keyword="MFCDLLProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="Nero\Include"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="NeroAPIGlue.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="Nero\Lib"
+				IgnoreDefaultLibraryNames="libcmt.lib"
+				ModuleDefinitionFile=".\Burndiscs.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy IBurndisc.h ..\BurndiscTest2\ /Y /A&#x0D;&#x0A;xcopy Nero.h ..\BurndiscTest2\ /Y /A"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="Nero\Include"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="NeroAPIGlue.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="Nero\Lib"
+				IgnoreDefaultLibraryNames="libcmt.lib"
+				ModuleDefinitionFile=".\Burndiscs.def"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy IBurndisc.h ..\BurndiscTest2\ /Y /A&#x0D;&#x0A;xcopy Nero.h ..\BurndiscTest2\ /Y /A"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="源文件"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Burndiscs.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Burndiscs.def"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="头文件"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Burndiscs.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="资源文件"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\Burndiscs.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\Burndiscs.rc2"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="接口"
+			>
+			<File
+				RelativePath=".\IBurndisc.h"
+				>
+			</File>
+			<File
+				RelativePath=".\IMAPI2Impl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\IMAPI2Impl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\NeroImpl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\NeroImpl.h"
+				>
+			</File>
+			<Filter
+				Name="IMAPI2"
+				>
+				<File
+					RelativePath=".\DiscFormatData.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscFormatData.h"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscFormatDataEvent.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscFormatDataEvent.h"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscMaster.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscMaster.h"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscRecorder.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\DiscRecorder.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="NeroSDK"
+				>
+				<File
+					RelativePath=".\Nero.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroBurndisc.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroBurndisc.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroDevice.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroDevice.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroItem.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroItem.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroMedia.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NeroMedia.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="iconv"
+			>
+			<File
+				RelativePath=".\iconv_impl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\iconv_impl.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 178 - 0
Burndiscs/Burndiscs/Burndiscs.vcxproj

@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{F4F79445-2FBE-412C-824F-5D9DF7F32D3F}</ProjectGuid>
+    <RootNamespace>Burndiscs</RootNamespace>
+    <Keyword>MFCDLLProj</Keyword>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>Unicode</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v141</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>15.0.27428.2015</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(ProjectName)\$(Configuration)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(ProjectName)\$(Configuration)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>Nero\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>NeroAPIGlue.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>Nero\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\Burndiscs.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy IBurndisc.h ..\BurndiscTest2\ /Y /A
+xcopy Nero.h ..\BurndiscTest2\ /Y /A</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+    </Midl>
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <AdditionalIncludeDirectories>Nero\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>NeroAPIGlue.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>Nero\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>libcmt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <ModuleDefinitionFile>.\Burndiscs.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <PostBuildEvent>
+      <Command>xcopy IBurndisc.h ..\BurndiscTest2\ /Y /A
+xcopy Nero.h ..\BurndiscTest2\ /Y /A</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="Burndiscs.cpp" />
+    <ClCompile Include="DiscFormatData.cpp" />
+    <ClCompile Include="DiscFormatDataEvent.cpp" />
+    <ClCompile Include="DiscMaster.cpp" />
+    <ClCompile Include="DiscRecorder.cpp" />
+    <ClCompile Include="iconv_impl.cpp" />
+    <ClCompile Include="IMAPI2Impl.cpp" />
+    <ClCompile Include="NeroBurndisc.cpp" />
+    <ClCompile Include="NeroDevice.cpp" />
+    <ClCompile Include="NeroImpl.cpp" />
+    <ClCompile Include="NeroItem.cpp" />
+    <ClCompile Include="NeroMedia.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Burndiscs.def" />
+    <None Include="res\Burndiscs.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Burndiscs.h" />
+    <ClInclude Include="DiscFormatData.h" />
+    <ClInclude Include="DiscFormatDataEvent.h" />
+    <ClInclude Include="DiscMaster.h" />
+    <ClInclude Include="DiscRecorder.h" />
+    <ClInclude Include="IBurndisc.h" />
+    <ClInclude Include="iconv_impl.h" />
+    <ClInclude Include="IMAPI2Impl.h" />
+    <ClInclude Include="Nero.h" />
+    <ClInclude Include="NeroBurndisc.h" />
+    <ClInclude Include="NeroDevice.h" />
+    <ClInclude Include="NeroImpl.h" />
+    <ClInclude Include="NeroItem.h" />
+    <ClInclude Include="NeroMedia.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="Burndiscs.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 139 - 0
Burndiscs/Burndiscs/Burndiscs.vcxproj.filters

@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+    <Filter Include="接口">
+      <UniqueIdentifier>{5116d9df-a77c-4e1c-9412-24ef4462873f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="接口\IMAPI2">
+      <UniqueIdentifier>{f2d0d0d0-394c-424e-8371-30d9587da3d8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="接口\NeroSDK">
+      <UniqueIdentifier>{0e3f7913-81ae-4b71-99bf-02f2190bccba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="iconv">
+      <UniqueIdentifier>{1584619a-e2b6-483b-b654-cbf4cba0fe6a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Burndiscs.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="IMAPI2Impl.cpp">
+      <Filter>接口</Filter>
+    </ClCompile>
+    <ClCompile Include="NeroImpl.cpp">
+      <Filter>接口</Filter>
+    </ClCompile>
+    <ClCompile Include="DiscFormatData.cpp">
+      <Filter>接口\IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="DiscFormatDataEvent.cpp">
+      <Filter>接口\IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="DiscMaster.cpp">
+      <Filter>接口\IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="DiscRecorder.cpp">
+      <Filter>接口\IMAPI2</Filter>
+    </ClCompile>
+    <ClCompile Include="NeroBurndisc.cpp">
+      <Filter>接口\NeroSDK</Filter>
+    </ClCompile>
+    <ClCompile Include="NeroDevice.cpp">
+      <Filter>接口\NeroSDK</Filter>
+    </ClCompile>
+    <ClCompile Include="NeroItem.cpp">
+      <Filter>接口\NeroSDK</Filter>
+    </ClCompile>
+    <ClCompile Include="NeroMedia.cpp">
+      <Filter>接口\NeroSDK</Filter>
+    </ClCompile>
+    <ClCompile Include="iconv_impl.cpp">
+      <Filter>iconv</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Burndiscs.def">
+      <Filter>源文件</Filter>
+    </None>
+    <None Include="res\Burndiscs.rc2">
+      <Filter>资源文件</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Burndiscs.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="IBurndisc.h">
+      <Filter>接口</Filter>
+    </ClInclude>
+    <ClInclude Include="IMAPI2Impl.h">
+      <Filter>接口</Filter>
+    </ClInclude>
+    <ClInclude Include="NeroImpl.h">
+      <Filter>接口</Filter>
+    </ClInclude>
+    <ClInclude Include="DiscFormatData.h">
+      <Filter>接口\IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="DiscFormatDataEvent.h">
+      <Filter>接口\IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="DiscMaster.h">
+      <Filter>接口\IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="DiscRecorder.h">
+      <Filter>接口\IMAPI2</Filter>
+    </ClInclude>
+    <ClInclude Include="Nero.h">
+      <Filter>接口\NeroSDK</Filter>
+    </ClInclude>
+    <ClInclude Include="NeroBurndisc.h">
+      <Filter>接口\NeroSDK</Filter>
+    </ClInclude>
+    <ClInclude Include="NeroDevice.h">
+      <Filter>接口\NeroSDK</Filter>
+    </ClInclude>
+    <ClInclude Include="NeroItem.h">
+      <Filter>接口\NeroSDK</Filter>
+    </ClInclude>
+    <ClInclude Include="NeroMedia.h">
+      <Filter>接口\NeroSDK</Filter>
+    </ClInclude>
+    <ClInclude Include="iconv_impl.h">
+      <Filter>iconv</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="Burndiscs.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+</Project>

+ 364 - 0
Burndiscs/Burndiscs/DiscFormatData.cpp

@@ -0,0 +1,364 @@
+#include "StdAfx.h"
+#include "DiscFormatData.h"
+#include "DiscRecorder.h"
+#include "DiscFormatDataEvent.h"
+
+
+CDiscFormatData::CDiscFormatData(void)
+: m_discFormatData(NULL)
+, m_mediaTypesArray(NULL)
+, m_supportedSpeeds(NULL)
+, m_hResult(0)
+, m_hNotificationWnd(NULL)
+, m_closeMedia(true)
+{
+}
+
+CDiscFormatData::~CDiscFormatData(void)
+{
+	if (m_discFormatData != NULL)
+	{
+		m_discFormatData->Release();
+		m_discFormatData = NULL;
+	}
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscFormatData::Initialize()
+//
+// Description:
+//		Creates and initializes the IDiscFormat2Data interface
+//
+bool CDiscFormatData::Initialize(CDiscRecorder* pDiscRecorder, const CString& clientName)
+{
+	ASSERT(m_discFormatData == NULL);
+	ASSERT(pDiscRecorder != NULL);
+	if (pDiscRecorder == NULL)
+	{
+		m_errorMessage = _T("Error - CDiscFormatData::Initialize - pDiscRecorder is NULL");
+		return false;
+	}
+
+	//
+	// Initialize the IDiscFormat2Data Interface
+	//
+	m_hResult = CoCreateInstance(__uuidof(MsftDiscFormat2Data), NULL, CLSCTX_INPROC_SERVER,
+			__uuidof(IDiscFormat2Data), (void**)&m_discFormatData);
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("Unable to Initialize IDiscFormat2Data - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	//
+	// Setup the Disc Format Information
+	//
+	m_hResult = m_discFormatData->get_SupportedMediaTypes(&m_mediaTypesArray); // 获取本系统内所有光驱支持的媒体格式 两个光驱则是罗列两个光驱的所有媒体格式
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("IDiscFormat2Data->get_SupportedMediaTypes Failed - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	//SAFEARRAY*	pSafeArray;
+	m_hResult = pDiscRecorder->GetInterface()->get_SupportedProfiles(&m_mediaTypesArray);  // 此时是获取一个光驱的支持媒体格式
+	if(!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("IDiscRecorder2->get_SupportedProfiles Failed - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+
+	VARIANT_BOOL isSupported = VARIANT_FALSE;
+	m_hResult = m_discFormatData->IsRecorderSupported(pDiscRecorder->GetInterface(), &isSupported);
+	if (isSupported == VARIANT_FALSE)
+	{
+		m_errorMessage = _T("Recorder not supported");
+		return false;
+	}
+
+	m_hResult = m_discFormatData->put_Recorder(pDiscRecorder->GetInterface());
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("IDiscFormat2Data->put_Recorder Failed - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	m_hResult = m_discFormatData->put_ClientName(clientName.AllocSysString());
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("IDiscFormat2Data->put_ClientName Failed - Error:0x%08x"), m_hResult);
+		return false;
+	}
+	// 检索当前刻录机或当前媒体支持的写入速度列表;
+	m_hResult = m_discFormatData->get_SupportedWriteSpeeds(&m_supportedSpeeds);
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_errorMessage.Format(_T("IDiscFormat2Data->get_SupportedWriteSpeeds Failed - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	return true;
+}
+
+ULONG CDiscFormatData::GetTotalSupportedMediaTypes()
+{
+	if (m_mediaTypesArray == NULL)
+		return 0;
+
+	return m_mediaTypesArray->rgsabound[0].cElements;
+}
+
+int CDiscFormatData::GetSupportedMediaType(ULONG index)
+{
+	ASSERT(index < GetTotalSupportedMediaTypes());
+	if (index < GetTotalSupportedMediaTypes())
+	{
+		if (m_mediaTypesArray)
+		{
+			return ((VARIANT*)(m_mediaTypesArray->pvData))[index].intVal;
+		}
+	}
+
+	return 0;
+}
+
+ULONG CDiscFormatData::GetTotalSupportedWriteSpeeds()
+{
+	if (m_supportedSpeeds == NULL)
+		return 0;
+
+	return m_supportedSpeeds->rgsabound[0].cElements;
+}
+
+int CDiscFormatData::GetSupportedWriteSpeed(ULONG index)
+{
+	ASSERT(index < GetTotalSupportedWriteSpeeds());
+
+	if ( index < GetTotalSupportedWriteSpeeds())
+	{
+		if (m_supportedSpeeds)
+			return ((VARIANT*)(m_supportedSpeeds->pvData))[index].ulVal;	// 每秒写入的扇区数;
+	}
+
+	return 0;
+}
+
+bool CDiscFormatData::SetWriteSpeed(ULONG index)
+{
+	ASSERT(index < GetTotalSupportedWriteSpeeds());
+	if ( index < GetTotalSupportedWriteSpeeds())
+	{
+		if (m_supportedSpeeds)
+			m_discFormatData->SetWriteSpeed(((VARIANT*)(m_supportedSpeeds->pvData))[index].ulVal, VARIANT_FALSE);
+	}
+
+	return false;
+}
+
+/*
+bool CDiscFormatData::SetBurnVerification(IMAPI_BURN_VERIFICATION_LEVEL VerificationLevel)
+{
+	HRESULT hr = S_OK;
+	IBurnVerification *burnVerifier = NULL;
+
+	hr = m_discFormatData->QueryInterface(IID_PPV_ARGS(&burnVerifier));
+
+	if (SUCCEEDED(hr))
+	{
+		hr = burnVerifier->put_BurnVerificationLevel(VerificationLevel);
+	}
+
+	if (burnVerifier != NULL)
+	{
+		burnVerifier->Release();
+		burnVerifier = NULL;
+	}
+
+	return hr;
+}*/
+
+bool CDiscFormatData::Burn(HWND hNotificationWnd, IStream* streamData)
+{
+	if (m_discFormatData == NULL)
+		return false;
+
+	if (streamData == NULL)
+		return false;
+
+	m_streamData = streamData;
+	m_hNotificationWnd = hNotificationWnd;
+
+	// Create the event sink
+	CDiscFormatDataEvent* eventSink = CDiscFormatDataEvent::CreateEventSink();
+	if (eventSink == NULL)
+	{
+		m_errorMessage = _T("Unable to create event sink");
+		return false;
+	}
+
+	if (!eventSink->ConnectDiscFormatData(this))
+	{
+		m_errorMessage = _T("Unable to connect event sink with interface");
+		return false;
+	}
+
+	eventSink->SetHwnd(m_hNotificationWnd);
+
+	m_discFormatData->put_ForceMediaToBeClosed(m_closeMedia ? VARIANT_TRUE : VARIANT_FALSE);
+
+
+	m_hResult = m_discFormatData->Write(m_streamData);
+
+	delete eventSink;
+
+	if (SUCCEEDED(m_hResult))
+	{
+		return true;
+	}
+
+	m_errorMessage.Format(_T("IDiscFormat2Data->Write Failed! Error:0x%08x"),
+		m_hResult);
+
+	return false;
+
+}
+
+CString CDiscFormatData::GetWriteErrorMsg(HRESULT hr)
+{
+	CString cstrWriteError;
+	switch(hr)
+	{
+	case 0xC0AA020D:
+		cstrWriteError = _T("超时");
+		break;
+	case 0xC0AA02FF:
+		cstrWriteError = _T("异常或者数据无效");
+		break;
+	case 0xC0AA0204:
+		cstrWriteError = _T("光盘放颠倒了");
+		break;
+	case 0xC0AA0205:
+		cstrWriteError = _T("准备中,稍后可能需要继续调用Write函数");
+		break;
+	case 0xC0AA0202:
+		cstrWriteError = _T("光驱中无光盘");
+		break;
+	case 0xC0AA0206:
+		cstrWriteError = _T("media正在格式化,请稍等");
+		break;
+	case 0xC0AA0207:
+		cstrWriteError = _T("光驱可能已经长时间工作,现在需要停止工作一会");
+		break;
+	case 0xC0AA0203:
+		cstrWriteError = _T("光盘不兼容或者未知的物理格式");
+		break;
+	case 0xC0AA0201:
+		cstrWriteError = _T("光驱要求的页模式,应用程序未提供");
+		break;
+	case 0xC0AA0208:
+		cstrWriteError = _T("模式页不支持");
+		break;
+	case 0xC0AA0209:
+		cstrWriteError = _T("光盘写保护");
+		break;
+	case 0xC0AA020F:
+		cstrWriteError = _T("写入的速度不匹配");
+		break;
+	case 6:
+		cstrWriteError = _T("句柄无效");
+		break;
+	case 55:
+		cstrWriteError = _T("网络异常或者光驱被卸载");
+		break;
+	case 0xC0AA0210:
+		cstrWriteError = _T("光驱正在被其他的写入独占");  // 
+		break;
+	case 0xC0AA0301:
+		cstrWriteError = _T("光驱报告异常");
+		break;
+	case 0xC0AA0003:
+		cstrWriteError = _T("写入动作没有指定光驱");
+		break;
+	case 0x00AA0005:
+		cstrWriteError = _T("要求的旋转时刻录,光驱不支持");
+		break;
+	case 0x00AA0004:
+		cstrWriteError = _T("要求的刻录速度光驱不支持,光驱已自行调整刻录速度");
+		break;
+	case 0x00AA0006:
+		cstrWriteError = _T("要求的旋转刻录和刻录速度不支持,光驱已经自行匹配");
+		break;
+	case 0xC0AA0407:
+		cstrWriteError = _T("光驱不支持光盘的格式");
+		break;
+	case 0xC0AA0002:
+		cstrWriteError = _T("操作取消");
+		break;
+	case 0xC0AA0400:
+		cstrWriteError = _T("另一个写入操作与此操作冲突"); //
+		break;
+	case 0xC0AA0403:
+		cstrWriteError = _T("提供的IStream大小无效.The size must be a multiple of the sector size, 2048.");
+		break;
+	case 0x80070057:
+		cstrWriteError = _T("一个或多个操作无效");
+		break;
+	case 0x80004003:
+		cstrWriteError = _T("指针无效");
+		break;
+	case 0x80004005:
+		cstrWriteError = _T("未知的失败");
+		break;
+	case 0x8007000E:
+		cstrWriteError = _T("内存不足");
+		break;
+	case 0x80004001:
+		cstrWriteError = _T("未知");
+		break;
+	case 0xC0AA0300:
+		cstrWriteError = _T("The write failed because the drive did not receive data quickly enough to continue writing");
+		break;
+	case 0xC0AA020E:
+		cstrWriteError = _T("DVD设备未找到");
+		break;
+	}
+	CString strTemp; 
+	strTemp .Format(_T(" 错误号:0x%x,"),hr);
+	cstrWriteError += strTemp;
+	return cstrWriteError;
+}
+
+/************************************************************************/
+/*  函数:获取媒体总扇区大小(不是空闲扇区大小)[3/20/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CDiscFormatData::GetFreeSectorsOnMedia(LONG& lFreeSectorOnMedia)
+{
+	if (m_discFormatData == NULL)
+		return false;
+
+	HRESULT hr = m_discFormatData->get_FreeSectorsOnMedia(&lFreeSectorOnMedia); 
+
+	if (SUCCEEDED(hr))
+	{
+		lFreeSectorOnMedia *= 2;
+		lFreeSectorOnMedia /= 1024;
+		//lFreeSectorOnMedia /= 1024;
+		return true;
+	}
+
+	return false;
+}

+ 86 - 0
Burndiscs/Burndiscs/DiscFormatData.h

@@ -0,0 +1,86 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __DISC_FORMAT_DATA__
+#define __DISC_FORMAT_DATA__
+
+#pragma once
+
+#define RETURN_CANCEL_WRITE	0
+#define RETURN_CONTINUE		1
+#define WM_IMAPI_UPDATE		WM_APP+842
+
+typedef struct _IMAPI_STATUS {
+	// IDiscFormat2DataEventArgs Interface
+	LONG elapsedTime;		// Elapsed time in seconds
+	LONG remainingTime;		// Remaining time in seconds
+	LONG totalTime;			// total estimated time in seconds
+	// IWriteEngine2EventArgs Interface
+	LONG startLba;			// the starting lba of the current operation
+	LONG sectorCount;		// the total sectors to write in the current operation
+	LONG lastReadLba;		// the last read lba address
+	LONG lastWrittenLba;	// the last written lba address
+	LONG totalSystemBuffer;	// total size of the system buffer
+	LONG usedSystemBuffer;	// size of used system buffer
+	LONG freeSystemBuffer;	// size of the free system buffer
+} IMAPI_STATUS, *PIMAPI_STATUS;
+
+// 前置声明;
+class CDiscRecorder;
+
+class CDiscFormatData
+{
+	IDiscFormat2Data*	m_discFormatData;
+	SAFEARRAY*			m_mediaTypesArray;
+	SAFEARRAY*			m_supportedSpeeds;
+	HRESULT				m_hResult;
+	CString				m_errorMessage;
+	HWND				m_hNotificationWnd;
+	bool				m_closeMedia;
+
+
+public:
+	CDiscFormatData(void);
+	~CDiscFormatData(void);
+
+	inline	HRESULT GetHresult() {return m_hResult;}
+	inline	CString GetErrorMessage() {return m_errorMessage;}
+
+	inline	IDiscFormat2Data* GetInterface() {return m_discFormatData;}
+	bool	Initialize(CDiscRecorder* pDiscRecorder, const CString& clientName);
+
+	bool	Burn(HWND hWnd, IStream* data);
+
+	ULONG	GetTotalSupportedMediaTypes();
+	int		GetSupportedMediaType(ULONG index);
+
+	ULONG	GetTotalSupportedWriteSpeeds();
+	int		GetSupportedWriteSpeed(ULONG index);
+	bool	SetWriteSpeed(ULONG index);
+
+	inline	void SetCloseMedia(bool closeMedia){m_closeMedia = closeMedia;}
+
+	//bool SetBurnVerification(IMAPI_BURN_VERIFICATION_LEVEL VerificationLevel);
+	static CString CDiscFormatData::GetWriteErrorMsg(HRESULT hr);
+	// 获取光盘的可用大小;
+	bool	GetFreeSectorsOnMedia(LONG& lFreeSectorOnMedia);
+
+protected:
+	IStream*	m_streamData;
+};
+
+#endif

+ 220 - 0
Burndiscs/Burndiscs/DiscFormatDataEvent.cpp

@@ -0,0 +1,220 @@
+#include "StdAfx.h"
+#include "DiscFormatDataEvent.h"
+#include "DiscFormatData.h"
+#include "afxctl.h"
+// CDiscFormatDataEvent
+
+IMPLEMENT_DYNAMIC(CDiscFormatDataEvent, CCmdTarget)
+
+BEGIN_INTERFACE_MAP(CDiscFormatDataEvent, CCmdTarget)
+	INTERFACE_PART(CDiscFormatDataEvent, IID_IDispatch, FormatDataEvents)
+	INTERFACE_PART(CDiscFormatDataEvent, IID_DDiscFormat2DataEvents, FormatDataEvents)
+END_INTERFACE_MAP()
+
+CDiscFormatDataEvent::CDiscFormatDataEvent()
+: m_hNotifyWnd(NULL)
+, m_ptinfo(NULL)
+, m_dwCookie(0)
+, m_pUnkSink(0)
+, m_pUnkSrc(0)
+{
+}
+
+CDiscFormatDataEvent::~CDiscFormatDataEvent()
+{
+	if (m_dwCookie && (m_pUnkSrc != NULL) && (m_pUnkSink != NULL))
+	{
+		AfxConnectionUnadvise(m_pUnkSrc, IID_DDiscFormat2DataEvents, m_pUnkSink,TRUE, m_dwCookie);
+	}
+}
+
+
+BEGIN_MESSAGE_MAP(CDiscFormatDataEvent, CCmdTarget)
+END_MESSAGE_MAP()
+
+
+
+// CDiscFormatDataEvent message handlers
+
+ULONG FAR EXPORT CDiscFormatDataEvent::XFormatDataEvents::AddRef()
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		return pThis->ExternalAddRef();
+}
+
+ULONG FAR EXPORT CDiscFormatDataEvent::XFormatDataEvents::Release()
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		return pThis->ExternalRelease();
+}
+
+STDMETHODIMP CDiscFormatDataEvent::XFormatDataEvents::QueryInterface(REFIID riid,LPVOID FAR* ppvObj)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		return (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
+}
+
+STDMETHODIMP CDiscFormatDataEvent::XFormatDataEvents::GetTypeInfoCount(UINT FAR* pctinfo)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		*pctinfo = 1;
+	return NOERROR;
+}
+
+STDMETHODIMP CDiscFormatDataEvent::XFormatDataEvents::GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo FAR* FAR* pptinfo)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		*pptinfo = NULL;
+
+	if(itinfo != 0)
+		return ResultFromScode(DISP_E_BADINDEX);
+	pThis->m_ptinfo->AddRef();
+	*pptinfo = pThis->m_ptinfo;
+	return NOERROR;
+}
+
+STDMETHODIMP CDiscFormatDataEvent::XFormatDataEvents::GetIDsOfNames(
+	REFIID riid,
+	OLECHAR FAR* FAR* rgszNames,
+	UINT cNames,
+	LCID lcid,
+	DISPID FAR* rgdispid)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+		return DispGetIDsOfNames(pThis->m_ptinfo, rgszNames, cNames, rgdispid);
+}
+
+STDMETHODIMP CDiscFormatDataEvent::XFormatDataEvents::Invoke(
+	DISPID dispidMember,
+	REFIID riid,
+	LCID lcid,
+	WORD wFlags,
+	DISPPARAMS FAR* pdispparams,
+	VARIANT FAR* pvarResult,
+	EXCEPINFO FAR* pexcepinfo,
+	UINT FAR* puArgErr)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+
+		return DispInvoke(&pThis->m_xFormatDataEvents, pThis->m_ptinfo,
+		dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscFormatDataEvent::CreateEventSink
+//
+// Description:
+//			Establishes a link between the CDiscFormatData(IDiscFormat2Data)
+//			and the CDiscFormatDataEvent(DDiscFormat2DataEvents) so 
+//			CDiscFormatDataEvent can receive Update messages
+//
+CDiscFormatDataEvent* CDiscFormatDataEvent::CreateEventSink()
+{
+	// Create the event sink
+	CDiscFormatDataEvent* pDiscFormatDataEvent = new CDiscFormatDataEvent();
+
+	pDiscFormatDataEvent->EnableAutomation();
+	pDiscFormatDataEvent->ExternalAddRef();
+
+	return pDiscFormatDataEvent;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscFormatDataEvent::ConnectDiscFormatData
+//
+// Description:
+//			Establishes a link between the CDiscFormatData(IDiscFormat2Data)
+//			and the CDiscFormatDataEvent(DDiscFormat2DataEvents) so 
+//			CDiscFormatDataEvent can receive Update messages
+//
+bool CDiscFormatDataEvent::ConnectDiscFormatData(CDiscFormatData* pDiscFormatData)
+{
+	m_pUnkSink = GetIDispatch(FALSE);
+	m_pUnkSrc = pDiscFormatData->GetInterface();
+
+	LPTYPELIB ptlib = NULL;
+	HRESULT hr = LoadRegTypeLib(LIBID_IMAPILib2, 
+		IMAPILib2_MajorVersion, IMAPILib2_MinorVersion, 
+		LOCALE_SYSTEM_DEFAULT, &ptlib);
+	if (FAILED(hr))
+	{
+		return false;
+	}
+	hr = ptlib->GetTypeInfoOfGuid(IID_DDiscFormat2DataEvents, &m_ptinfo);
+	ptlib->Release();
+	if (FAILED(hr))
+	{
+		return false;
+	}
+
+	BOOL bRet = AfxConnectionAdvise(m_pUnkSrc, IID_DDiscFormat2DataEvents, m_pUnkSink,
+		TRUE, &m_dwCookie);
+	if (bRet)
+	{
+		return true;
+	}
+
+	return false;
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscFormatDataEvent::Update
+//
+// Description:
+//			Receives update notifications from IDiscFormat2Data
+//
+STDMETHODIMP_(HRESULT) CDiscFormatDataEvent::XFormatDataEvents::Update(IDispatch* objectDispatch, IDispatch* progressDispatch)
+{
+	METHOD_PROLOGUE(CDiscFormatDataEvent, FormatDataEvents)
+
+		IDiscFormat2DataEventArgs* progress = NULL;
+	HRESULT hr = progressDispatch->QueryInterface(IID_PPV_ARGS(&progress));
+
+	IDiscFormat2Data* discFormatData = NULL;
+	hr = objectDispatch->QueryInterface(IID_PPV_ARGS(&discFormatData));
+
+	IMAPI_FORMAT2_DATA_WRITE_ACTION currentAction = IMAPI_FORMAT2_DATA_WRITE_ACTION_VALIDATING_MEDIA;
+	hr = progress->get_CurrentAction(&currentAction);
+	ASSERT(SUCCEEDED(hr));
+	if (FAILED(hr))
+	{
+		return S_OK;
+	}
+
+	IMAPI_STATUS imapiStatus = {0};
+
+	if ((currentAction == IMAPI_FORMAT2_DATA_WRITE_ACTION_WRITING_DATA) ||
+		(currentAction == IMAPI_FORMAT2_DATA_WRITE_ACTION_FINALIZATION))
+	{
+		progress->get_ElapsedTime(&imapiStatus.elapsedTime);
+		progress->get_RemainingTime(&imapiStatus.remainingTime);
+		progress->get_TotalTime(&imapiStatus.totalTime);
+
+		if (currentAction == IMAPI_FORMAT2_DATA_WRITE_ACTION_WRITING_DATA)
+		{
+			progress->get_StartLba(&imapiStatus.startLba);
+			progress->get_SectorCount(&imapiStatus.sectorCount);
+			progress->get_LastReadLba(&imapiStatus.lastReadLba);
+			progress->get_LastWrittenLba(&imapiStatus.lastWrittenLba);
+			progress->get_TotalSystemBuffer(&imapiStatus.totalSystemBuffer);
+			progress->get_UsedSystemBuffer(&imapiStatus.usedSystemBuffer);
+			progress->get_FreeSystemBuffer(&imapiStatus.freeSystemBuffer);
+		}
+	}
+
+	if ( pThis->m_hNotifyWnd )
+	{	
+		LRESULT ret = ::SendMessage(pThis->m_hNotifyWnd, WM_IMAPI_UPDATE, currentAction, (LPARAM)(LPVOID)&imapiStatus);
+		if (ret == RETURN_CANCEL_WRITE)
+		{
+			discFormatData->CancelWrite();
+		}
+	}
+
+	return S_OK;
+}

+ 70 - 0
Burndiscs/Burndiscs/DiscFormatDataEvent.h

@@ -0,0 +1,70 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __DISC_FORMAT_DATA_EVENT__
+#define __DISC_FORMAT_DATA_EVENT__
+
+#pragma once
+#include "afxwin.h"
+
+class CDiscFormatData;
+
+class CDiscFormatDataEvent :
+	public CCmdTarget
+{
+	DECLARE_DYNAMIC(CDiscFormatDataEvent)
+private:
+	LPTYPEINFO  m_ptinfo;           // ITest type information
+	DWORD		m_dwCookie;
+	LPUNKNOWN	m_pUnkSink;
+	LPUNKNOWN	m_pUnkSrc;
+
+	HWND		m_hNotifyWnd;
+
+public:
+	CDiscFormatDataEvent();
+	virtual ~CDiscFormatDataEvent();
+
+	static CDiscFormatDataEvent* CreateEventSink();
+
+	bool ConnectDiscFormatData(CDiscFormatData*);
+	inline void SetHwnd(HWND hWnd){m_hNotifyWnd = hWnd;}
+
+	DECLARE_INTERFACE_MAP()
+
+	BEGIN_INTERFACE_PART(FormatDataEvents, DDiscFormat2DataEvents)
+		//
+		// IDispatch Methods
+		//
+		STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo);
+		STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo);
+		STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,
+			UINT cNames, LCID lcid, DISPID FAR* rgdispid);
+		STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid,
+			WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult,
+			EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr);
+		//
+		// DDiscFormat2DataEvents Methods
+		//
+		STDMETHOD_(HRESULT, Update)(LPDISPATCH, LPDISPATCH);
+	END_INTERFACE_PART(FormatDataEvents)
+
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+#endif

+ 134 - 0
Burndiscs/Burndiscs/DiscMaster.cpp

@@ -0,0 +1,134 @@
+#include "StdAfx.h"
+#include "DiscMaster.h"
+
+CDiscMaster::CDiscMaster(void)
+:m_pDiscMaster(NULL)
+,m_hResult(0)
+{
+}
+
+CDiscMaster::~CDiscMaster(void)
+{
+	if ( m_pDiscMaster )
+		m_pDiscMaster->Release();
+	m_pDiscMaster = NULL;
+}
+
+/************************************************************************/
+/*  函数:[3/20/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CDiscMaster::Initialize()
+{
+	ASSERT(m_pDiscMaster == NULL);
+
+	// 初始化接口IDiscMaster2; 
+	if ( m_pDiscMaster == NULL )
+	{
+		m_hResult = CoCreateInstance(__uuidof(MsftDiscMaster2), NULL, CLSCTX_INPROC_SERVER,__uuidof(IDiscMaster2), (void**)&m_pDiscMaster);
+		if (!SUCCEEDED(m_hResult))
+		{
+			m_strErrorMsg.Format(_T("Unable to Initialize IDiscMaster2 - Error:0x%08x"), m_hResult);
+			return false;
+		}
+	}
+
+	// 是否包含一个或多个光学设备,并且执行上下文有权访问设备;
+	VARIANT_BOOL isSupported = VARIANT_FALSE;
+	m_hResult = m_pDiscMaster->get_IsSupportedEnvironment(&isSupported);
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_IsSupportedEnvironment failed! - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	if (isSupported == VARIANT_FALSE)
+	{
+		// 没有设备或没有权限访问设备;
+		m_strErrorMsg = _T("There were no writable devices detected!");
+		return false;
+	}
+
+	return true;
+}
+
+
+/************************************************************************/
+/*  函数:检索计算机上安装的CD和DVD光盘设备的数量[3/20/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+long CDiscMaster::GetTotalDevices()
+{
+	ASSERT(m_pDiscMaster != NULL);
+	if (m_pDiscMaster == NULL)
+		return 0;
+
+	long totalDevices = 0;
+	// 检索计算机上安装的CD和DVD光盘设备的数量;
+	m_hResult = m_pDiscMaster->get_Count(&totalDevices);
+	if (FAILED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_Count failed! - Error:0x%08x"), m_hResult);
+		return 0;
+	}
+
+	return totalDevices;
+}
+
+/************************************************************************/
+/*  函数:检索指定磁盘设备的唯一标识符[3/20/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+CString CDiscMaster::GetDeviceUniqueID(long nIndex)
+{
+	ASSERT(m_pDiscMaster != NULL);
+	ASSERT(nIndex < GetTotalDevices());
+
+	BSTR	uniqueID = NULL;
+	// 检索指定磁盘设备的唯一标识符;
+	m_hResult = m_pDiscMaster->get_Item(nIndex, &uniqueID);
+	if (FAILED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_Item(%d) failed! - Error:0x%08x"),nIndex, m_hResult);
+		return _T("");
+	}
+
+#ifdef UNICODE
+	return uniqueID;
+#else
+	return CString((char*)_bstr_t(uniqueID));
+#endif
+}

+ 41 - 0
Burndiscs/Burndiscs/DiscMaster.h

@@ -0,0 +1,41 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __DISC_MASTER__
+#define __DISC_MASTER__
+
+#pragma once
+
+class CDiscMaster
+{
+	IDiscMaster2	*m_pDiscMaster;
+	HRESULT			m_hResult;
+	CString			m_strErrorMsg;
+
+public:
+	CDiscMaster(void);
+	~CDiscMaster(void);
+
+	inline HRESULT GetHResult() {return m_hResult;}
+	inline CString GetErrorMsg() {return m_strErrorMsg;}
+
+	bool Initialize();
+	long GetTotalDevices();
+	CString GetDeviceUniqueID(long nIndex);
+};
+
+#endif

+ 395 - 0
Burndiscs/Burndiscs/DiscRecorder.cpp

@@ -0,0 +1,395 @@
+#include "StdAfx.h"
+#include "DiscRecorder.h"
+
+
+#ifndef CDROM_EXCLUSIVE_CALLER_LENGTH
+#define CDROM_EXCLUSIVE_CALLER_LENGTH 64
+#endif
+
+CDiscRecorder::CDiscRecorder(void)
+	:m_pDiscRecorder(NULL)
+	, m_volumePathNames(NULL)
+	, m_hResult(0)
+{
+}
+
+CDiscRecorder::~CDiscRecorder(void)
+{
+	/*if (m_volumePathNames)
+		SafeArrayDestroy(m_volumePathNames);
+	m_volumePathNames = NULL;*/
+
+	if (m_pDiscRecorder)
+		m_pDiscRecorder->Release();
+	m_pDiscRecorder = NULL;
+}
+
+/************************************************************************/
+/*  函数:创建并初始化IDiscRecorder2接口实例[3/20/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] recorderUniqueId:IDiscMaster2接口实例返回的唯一ID;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CDiscRecorder::Initialize(const CString& recorderUniqueId)
+{
+	m_recorderUniqueId = recorderUniqueId;
+
+	//
+	// Create an IDiscRecorder2
+	//
+	m_hResult = CoCreateInstance(__uuidof(MsftDiscRecorder2), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiscRecorder2), (void**)&m_pDiscRecorder);
+	ASSERT(SUCCEEDED(m_hResult));
+	if (FAILED(m_hResult))
+	{
+		return false;
+	}
+
+	BSTR bstrUId = recorderUniqueId.AllocSysString();
+	m_hResult = m_pDiscRecorder->InitializeDiscRecorder(bstrUId);
+	if (FAILED(m_hResult))
+	{
+		SysFreeString(bstrUId);
+		return false;
+	}
+	SysFreeString(bstrUId);
+
+	//
+	// Get the volume name paths
+	//
+	m_hResult = m_pDiscRecorder->get_VolumePathNames(&m_volumePathNames);
+	ASSERT(SUCCEEDED(m_hResult));
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::AcquireExclusiveAccess()
+//
+// Description:
+//		Acquires exclusive access to this device
+//
+// Parameters:
+//		force		forces exclusive access whether or not the device
+//					can be dismounted
+//		clientName	The name of the client application
+//
+bool CDiscRecorder::AcquireExclusiveAccess(bool force, const CString& clientName)
+{
+	int length = clientName.GetLength();
+	ASSERT(!clientName.IsEmpty());
+	ASSERT(length < CDROM_EXCLUSIVE_CALLER_LENGTH);
+
+	if (length == 0 || length >= CDROM_EXCLUSIVE_CALLER_LENGTH)
+	{
+		return false;
+	}
+
+	for (int index = 0; index < length; index++)
+	{
+		TCHAR ch = clientName[index];
+		if (_istalnum(ch) || ch == _T(' ') || ch == _T('.') || ch == _T(',') ||
+			ch == _T(':') || ch == _T(';') || ch == _T('-') || ch == _T('_'))
+		{
+			continue;
+		}
+
+		//
+		// Client name does not meet specification
+		//
+		ASSERT(FALSE);
+		return false;
+	}
+
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->AcquireExclusiveAccess(
+			force ? VARIANT_TRUE : VARIANT_FALSE,
+			clientName.AllocSysString());
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::ReleaseExclusiveAccess()
+//
+// Description:
+//		Releases exclusive access to this device
+//
+bool CDiscRecorder::ReleaseExclusiveAccess()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->ReleaseExclusiveAccess();
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::ExclusiveAccessOwner()
+//
+// Description:
+//		Returns the name of the client who has exclusive access to this
+//		device.
+//
+CString CDiscRecorder::ExclusiveAccessOwner()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		BSTR owner = NULL;
+
+		m_hResult = m_pDiscRecorder->get_ExclusiveAccessOwner(&owner);
+		if (SUCCEEDED(m_hResult))
+		{
+#ifdef UNICODE
+			return owner;
+#else
+			return CString((char*)_bstr_t(owner));
+#endif
+		}
+	}
+
+	return _T("");
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::EjectMedia()
+//
+// Description:
+//		Elects the media on this device
+//
+bool CDiscRecorder::EjectMedia()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->EjectMedia();
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::CloseTray()
+//
+// Description:
+//		Closes the tray on this device
+//
+bool CDiscRecorder::CloseTray()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->CloseTray();
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::EnableMcn()
+//
+// Description:
+//		Enables the Media Change Notification on this device
+//
+bool CDiscRecorder::EnableMcn()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->EnableMcn();
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::DisableMcn()
+//
+// Description:
+//		Disables the Media Change Notification on this device
+//
+bool CDiscRecorder::DisableMcn()
+{
+	if (m_pDiscRecorder != NULL)
+	{
+		m_hResult = m_pDiscRecorder->DisableMcn();
+		if (SUCCEEDED(m_hResult))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::LegacyDeviceNumber()
+//
+// Description:
+//		Returns the legacy device number
+//
+LONG CDiscRecorder::GetLegacyDeviceNumber()
+{
+	LONG deviceNumber = 0;
+	if (m_pDiscRecorder != NULL)
+	{
+		m_pDiscRecorder->get_LegacyDeviceNumber(&deviceNumber);
+	}
+	return deviceNumber;
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::ProductRevision()
+//
+// Description:
+//		Returns the product id for this device
+//
+CString CDiscRecorder::GetProductID()
+{
+	BSTR productId = NULL;
+	if (m_pDiscRecorder != NULL)
+	{
+		m_pDiscRecorder->get_ProductId(&productId);
+	}
+
+#ifdef UNICODE
+	return productId;
+#else
+	return CString((char*)_bstr_t(productId));
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::ProductRevision()
+//
+// Description:
+//		Returns the product revision for this device
+//
+CString CDiscRecorder::GetProductRevision()
+{
+	BSTR productRevision = NULL;
+	if (m_pDiscRecorder != NULL)
+	{
+		m_pDiscRecorder->get_ProductRevision(&productRevision);
+	}
+
+#ifdef UNICODE
+	return productRevision;
+#else
+	return CString((char*)_bstr_t(productRevision));
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::VendorId()
+//
+// Description:
+//		Returns the vendor id for this device
+//
+CString CDiscRecorder::GetVendorId()
+{
+	BSTR vendorId = NULL;
+	if (m_pDiscRecorder != NULL)
+	{
+		m_pDiscRecorder->get_VendorId(&vendorId);
+	}
+
+#ifdef UNICODE
+	return vendorId;
+#else
+	return CString((char*)_bstr_t(vendorId));
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// CDiscRecorder::VolumeName()
+//
+// Description:
+//		Returns the unique volume name associated with this device
+//
+CString CDiscRecorder::GetVolumeName()
+{
+	BSTR volumeName = NULL;
+	if (m_pDiscRecorder != NULL)
+	{
+		m_pDiscRecorder->get_VolumeName(&volumeName);
+	}
+
+#ifdef UNICODE
+	return volumeName;
+#else
+	return CString((char*)_bstr_t(volumeName));
+#endif
+}
+
+ULONG CDiscRecorder::GetTotalVolumePaths()
+{
+	if (m_volumePathNames != NULL)
+	{
+		return m_volumePathNames->rgsabound[0].cElements;
+	}
+
+	return 0;
+}
+
+CString CDiscRecorder::GetVolumePath(ULONG volumePathIndex)
+{
+	ASSERT(volumePathIndex < m_volumePathNames->rgsabound[0].cElements);
+	if (volumePathIndex >= m_volumePathNames->rgsabound[0].cElements)
+	{
+		return _T("");
+	}
+
+#ifdef UNICODE
+	return ((VARIANT*)(m_volumePathNames->pvData))[volumePathIndex].bstrVal;
+#else
+	return CString((char*)_bstr_t(((VARIANT*)(m_volumePathNames->pvData))[volumePathIndex].bstrVal));
+#endif
+}
+
+CString CDiscRecorder::GetRecorderName()
+{
+	return GetVolumePath(0) + GetVendorId() + GetProductID();
+}

+ 63 - 0
Burndiscs/Burndiscs/DiscRecorder.h

@@ -0,0 +1,63 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __DISC_RECORDER__
+#define __DISC_RECORDER__
+
+#pragma once
+
+class CDiscRecorder
+{
+	IDiscRecorder2*		m_pDiscRecorder;
+	SAFEARRAY*			m_volumePathNames;
+	HRESULT				m_hResult;
+	CString				m_recorderUniqueId;
+public:
+	CDiscRecorder(void);
+	~CDiscRecorder(void);
+
+	inline HRESULT GetHresult() { return m_hResult; }
+	inline IDiscRecorder2* GetInterface() { return m_pDiscRecorder; }
+	inline CString GetUniqueId() { return m_recorderUniqueId; }
+
+	bool Initialize(const CString& recorderUniqueId);
+
+	// 独占设备使用权;
+	bool AcquireExclusiveAccess(bool force, const CString& clientName);
+	// 释放独占权限;
+	bool ReleaseExclusiveAccess();
+	CString ExclusiveAccessOwner();
+
+	// 弹出光盘;
+	bool EjectMedia();
+	bool CloseTray();
+
+	bool EnableMcn();
+	bool DisableMcn();
+
+	LONG	GetLegacyDeviceNumber();
+	CString GetProductID();
+	CString GetProductRevision();
+	CString GetVendorId();
+	CString GetVolumeName();
+
+	ULONG GetTotalVolumePaths();
+	CString GetVolumePath(ULONG volumePathIndex);
+	CString GetRecorderName();
+};
+
+#endif

+ 3 - 0
Burndiscs/Burndiscs/IBurndisc.cpp

@@ -0,0 +1,3 @@
+#include "StdAfx.h"
+#include "IBurndisc.h"
+

+ 101 - 0
Burndiscs/Burndiscs/IBurndisc.h

@@ -0,0 +1,101 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/20/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __I_BURN_DISC__
+#define __I_BURN_DISC__
+
+#pragma once
+
+#include "Nero.h"
+
+typedef struct __DEVINFO__
+{
+	int				nIndex;					// 设备索引;
+	TString			strDevName;				// 设备名称;
+	TString			strDevUId;				// 设备的id;
+	void*			pDevInfo;				// 设备对象;
+
+	__DEVINFO__() :nIndex(-1), pDevInfo(NULL) {	}
+}DeviceInfo, *pDeviceInfo;
+
+// {96D4FD2E-115A-474d-A5E0-D1400D14083B}
+static const GUID IID_IBurndisc =
+{ 0x96d4fd2e, 0x115a, 0x474d,{ 0xa5, 0xe0, 0xd1, 0x40, 0xd, 0x14, 0x8, 0x3b } };
+
+interface IBurndisc :public IUnknown
+{
+public:
+	// 初始化刻录环境;
+	virtual bool Initialize() = 0;
+
+	// 获取可用的设备数量;
+	virtual int GetAvailableDrives() = 0;
+
+	// 获取刻录机设备信息;
+	virtual void* GetDeivceInfo(int nIndex) = 0;
+	virtual void* GetDeivceInfo(const TCHAR *pszDevName) = 0;
+
+	// 添加文件或文件夹;
+	virtual void AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles) = 0;
+	virtual void AddFolder2Disc(TString strFatherNode, TString strFolder) = 0;
+	/*
+	// 获取媒体光盘的信息;
+	virtual void* GetMediaInfo(int nIndex) = 0;
+	virtual void* GetMediaInfo(const TCHAR *pszDevName) = 0;
+	virtual void* GetMediaInfo(void *pDevInfo) = 0;
+
+	// 获取设备的刻录速度;
+	virtual bool GetWriteSpeeds() = 0;
+
+	// 获取擦除设备的时长;
+	virtual bool GetCDRWErasingTime() = 0;
+
+	// 弹出或加载CD;
+	virtual bool EjectLoadCD() = 0;
+	*/
+	virtual void 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
+	) = 0;
+
+	virtual void IMAPI2Set(void* pDailog) = 0;
+
+	// 设置写速度;
+	virtual bool SetWriteSpeed(ULONG nIndex) = 0;
+
+	// 擦除设备;
+	virtual void EraseMedia(int nIndex) = 0;
+
+	// 写光盘;
+	virtual bool BurnMedia(int nIndex, TString strArtist, TString strTitle) = 0;
+
+};
+
+
+#endif

+ 897 - 0
Burndiscs/Burndiscs/IMAPI2Impl.cpp

@@ -0,0 +1,897 @@
+#include "StdAfx.h"
+#include "IMAPI2Impl.h"
+#include "DiscRecorder.h"
+#include "DiscFormatData.h"
+#include <imapi2fs.h>
+// stl 排序;
+//#include <cstdlib>
+#include <algorithm>
+
+CDialog *CIMAPI2Impl::m_pDailog = NULL;
+
+CIMAPI2Impl::CIMAPI2Impl(void)
+	:m_pDiscMaster(NULL)
+	, m_hResult(0)
+	, m_nRef(0)
+{
+	::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+}
+
+CIMAPI2Impl::~CIMAPI2Impl(void)
+{
+	for (vector<DeviceInfo>::iterator it = m_vtDevInfo.begin(); it != m_vtDevInfo.end(); it++)
+	{
+		if (it->pDevInfo)
+			delete (CDiscRecorder*)it->pDevInfo;
+		it->pDevInfo = NULL;
+	}
+	m_vtDevInfo.clear();
+
+	if (m_pDiscMaster)
+		m_pDiscMaster->Release();
+	m_pDiscMaster = NULL;
+
+	::CoUninitialize();
+}
+
+ULONG CIMAPI2Impl::AddRef()
+{
+	InterlockedIncrement(&m_nRef);
+	return m_nRef;
+}
+
+ULONG CIMAPI2Impl::Release()
+{
+	LONG ulRefCount = InterlockedDecrement(&m_nRef);
+	//如果为0,删除对象;
+	if (m_nRef == 0)
+	{
+		delete this;
+	}
+	return ulRefCount;
+}
+
+HRESULT CIMAPI2Impl::QueryInterface(REFIID riid, __RPC__deref_out void **ppvObject)
+{
+	if (!ppvObject)
+		return E_INVALIDARG;
+
+	*ppvObject = NULL;
+	if (riid == IID_IUnknown || riid == IID_IBurndisc)
+	{
+		*ppvObject = (LPVOID)this;
+		AddRef();
+		return NOERROR;
+	}
+
+	return E_NOINTERFACE;
+}
+
+/************************************************************************/
+/*  函数:[4/1/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:不要使用函数AcquireExclusiveAccess来独占设备的访问权限,否则image->ImportFileSystem一直失败(被害一个多星期) ;
+/*		如果要用独占权限, 先执行本函数后再独占就不会有问题.并且,IDiscFormatData2在Write时就会独占设备;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CIMAPI2Impl::CreateMediaFileSystem(void* pdiscfd, TString strVolumeName, IStream** dataStream)
+{
+	if (pdiscfd == NULL)
+		return false;
+
+	IFileSystemImage*		image = NULL;
+	IFileSystemImageResult*	imageResult = NULL;
+	IFsiDirectoryItem*		rootItem = NULL;
+	HRESULT hr = S_FALSE;
+
+	// 创建文件系统映像对象;
+	hr = CoCreateInstance(CLSID_MsftFileSystemImage, NULL, CLSCTX_ALL, __uuidof(IFileSystemImage), (void**)&image);
+	if (FAILED(hr))
+	{
+		// 释放;
+		if (image)
+			delete image;
+		image = NULL;
+
+		return false;
+	}
+
+	if (image == NULL)
+		return false;
+
+	CDiscFormatData *pdiscFormatData = (CDiscFormatData*)pdiscfd;
+	// 获取光盘支持的媒体格式;
+	IMAPI_MEDIA_PHYSICAL_TYPE mediaType = IMAPI_MEDIA_TYPE_UNKNOWN;
+	pdiscFormatData->GetInterface()->get_CurrentPhysicalMediaType(&mediaType);
+	// 根据光盘的媒体类型来设置文件系统的类型和大小;
+	image->ChooseImageDefaultsForMediaType(mediaType);
+
+	VARIANT_BOOL vbBlank = VARIANT_FALSE;
+	// 判断光盘是否为空白盘 vbBlank = VARIANT_TRUE则光盘为空白光盘;
+	pdiscFormatData->GetInterface()->get_MediaHeuristicallyBlank(&vbBlank);
+	if (vbBlank == VARIANT_TRUE)
+	{// 空白光盘;
+	 // 获取刻录机设备指针;
+		IDiscRecorder2 *pRecorder2 = NULL;
+		hr = pdiscFormatData->GetInterface()->get_Recorder(&pRecorder2);
+		if (FAILED(hr))
+		{
+			RELEASEP(image);
+			return false;
+		}
+
+		// 设置文件系统映像的卷名称;
+		hr = image->put_VolumeName(_bstr_t(strVolumeName.c_str()));
+		hr = image->ChooseImageDefaults(pRecorder2);
+		if (FAILED(hr))
+		{
+			RELEASEP(image);
+			return false;
+		}
+	}
+	else
+	{
+		// 存储光盘多会话;
+		SAFEARRAY *pSafeArrayMulSection = NULL;
+		// 检索光盘的多会话界面;
+		hr = pdiscFormatData->GetInterface()->get_MultisessionInterfaces(&pSafeArrayMulSection);
+		if (!SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			return false;
+		}
+
+#if 1
+		// 将光盘最后一个会话导入到文件系统中;
+		hr = image->put_MultisessionInterfaces(pSafeArrayMulSection);
+		if (!SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			return FALSE;
+		}
+
+		FsiFileSystems filesystem;
+		hr = image->ImportFileSystem(&filesystem);
+		if (!SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			return false;
+		}
+#else // 可能xp系统要用到以下方式,暂时保留;
+		long vale = 0;
+		// 检索下一个可写入操作的位置;
+		hr = pdiscFormatData->GetInterface()->get_NextWritableAddress(&vale);
+		if (SUCCEEDED(hr))
+		{
+			// 将光盘最后一个会话导入到文件系统中;
+			hr = image->put_MultisessionInterfaces(pSafeArrayMulSection);
+			if (!SUCCEEDED(hr))
+			{
+				RELEASEP(image);
+				return FALSE;
+			}
+
+			// 设置光盘之前的数据为已使用(这步是否必须?观VB代码,好像没有这步, 说ImportFileSystem会自动导入光盘的数据);
+			VARIANT *va = NULL;
+			SafeArrayAccessData(pSafeArrayMulSection, (VOID**)&va);
+			if (va)
+			{
+				IMultisession *pMultisession = NULL;
+				pMultisession = (IMultisession*)va[0].pdispVal;
+				hr = pMultisession->put_InUse(VARIANT_TRUE);
+				if (!SUCCEEDED(hr))
+				{
+					SafeArrayDestroy(pSafeArrayMulSection);
+					RELEASEP(image);
+					return FALSE;
+				}
+			}
+
+			//encounter IMAPI_E_IMPORT_SEEK_FAILURE or IMAPI_E_NO_SUPPORTED_FILE_SYSTEM
+			// 导入;
+			//FsiFileSystems filesystem;
+			//hr = image->get_FileSystemsSupported(&filesystem);
+			//hr = image->GetDefaultFileSystemForImport(filesystem,&filesystem); 
+			//hr = image->ImportSpecificFileSystem(filesystem);
+			hr = image->ImportFileSystem(&filesystem);
+			if (!SUCCEEDED(hr))
+			{
+				RELEASEP(image);
+				SafeArrayDestroy(pSafeArrayMulSection);
+				return false;
+			}
+		}// get_multisession OK
+#endif
+
+		SafeArrayDestroy(pSafeArrayMulSection);
+	}
+
+#if 0 // 判断光盘是否有足够的空间来刻录;
+	LONG lFreeSectorOnMedia = 0;
+	if (SUCCEEDED(hr))
+	{
+		hr = pdiscFormatData->GetInterface()->get_FreeSectorsOnMedia(&lFreeSectorOnMedia);
+		if (SUCCEEDED(hr))
+		{
+			hr = image->put_FreeMediaBlocks(lFreeSectorOnMedia);
+		}
+	}
+
+	// 光盘的每个扇区大小 = 2048 字节;
+	//	image->get_FreeMediaBlocks(&m_nFreeBlock); // 获取光盘的容积
+	ULONGLONG ulDiscSize = (ULONGLONG)lFreeSectorOnMedia * 2048; // 转换成字节数;
+	ULONGLONG ulFileSize = 0;
+	if (ulFileSize > (ulDiscSize - 1024 * 1024))
+	{
+		// 小于1M,无法刻录;
+		return false;
+	}
+#endif
+
+	// 获取文件根对象;
+	hr = image->get_Root(&rootItem);
+	if (!SUCCEEDED(hr))
+	{
+		// 清除...
+		RELEASEP(image);
+		RELEASEP(rootItem);
+		return false;
+	}
+
+	// 添加文件或目录;
+	IFsiItem* pFsiItem = NULL;
+	IStream* fileStream = NULL;
+	IFsiDirectoryItem* pFsiDir = NULL;
+	FsiItemType itemType = FsiItemNotFound;
+	for (vector<DiscPathFile>::iterator it = m_vtDiscItems.begin(); it != m_vtDiscItems.end(); it++)
+	{
+		hr = image->Exists(_bstr_t(it->strDiscPath.c_str()), &itemType);
+		if (SUCCEEDED(hr))
+		{
+			if (itemType == FsiItemNotFound)
+			{// 没有这个目录;
+				hr = image->CreateDirectoryItem(_bstr_t(it->strDiscPath.substr(1).c_str()), &pFsiDir);
+				if (SUCCEEDED(hr))
+				{
+					hr = rootItem->Add(pFsiDir);
+					if (FAILED(hr))
+					{
+						RELEASEP(pFsiDir);
+						continue;
+					}
+				}
+				else {
+					RELEASEP(pFsiDir);
+					continue;
+				}
+			}
+			else if (itemType == FsiItemDirectory)
+			{
+				hr = rootItem->get_Item(_bstr_t(it->strDiscPath.c_str()), &pFsiItem);
+				if (SUCCEEDED(hr))
+				{
+					pFsiDir = (IFsiDirectoryItem*)pFsiItem;
+				}
+				else
+					continue;
+			}
+		}
+		else
+		{
+			RELEASEP(pFsiDir);
+			continue;
+		}
+
+		for (vector<TString>::iterator it_dir = it->vtdirs.begin(); it_dir != it->vtdirs.end(); it_dir++)
+		{
+			hr = pFsiDir->AddTree(_bstr_t(it_dir->c_str()), VARIANT_TRUE);
+			if (FAILED(hr))
+			{
+				OutputDebugString(_T("dfdfdfdfdfdf"));
+			}
+		}
+
+		for (vector<TString>::iterator it_file = it->vtfiles.begin(); it_file != it->vtfiles.end(); it_file++)
+		{
+#ifdef UNICODE
+			hr = SHCreateStreamOnFileEx(it_file->c_str(),
+				STGM_READ | STGM_SHARE_DENY_NONE | STGM_DELETEONRELEASE,
+				FILE_ATTRIBUTE_NORMAL,
+				FALSE,
+				NULL,
+				&fileStream);
+#else
+			WCHAR szFile[MAX_PATH * 2] = { 0 };
+			TString strfile = convert("GBK", "UCS-2LE", it_file->c_str(), it_file->size());
+			memcpy(szFile, strfile.c_str(), strfile.size());
+			hr = SHCreateStreamOnFileEx(szFile,
+				STGM_READ | STGM_SHARE_DENY_NONE | STGM_DELETEONRELEASE,
+				FILE_ATTRIBUTE_NORMAL,
+				FALSE,
+				NULL,
+				&fileStream);
+#endif
+			if (SUCCEEDED(hr))
+			{
+				hr = pFsiDir->AddFile(_bstr_t(it_file->substr(it_file->find_last_of('\\') + 1).c_str()), fileStream);
+			}
+		}
+
+		RELEASEP(pFsiDir);
+	}
+
+	// 生成结果流文件系统;
+	hr = image->CreateResultImage(&imageResult);
+	if (SUCCEEDED(hr))
+	{
+		hr = imageResult->get_ImageStream(dataStream);
+		if (SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			RELEASEP(imageResult);
+			RELEASEP(rootItem);
+			return true;
+		}
+	}
+
+	RELEASEP(image);
+	RELEASEP(imageResult);
+	RELEASEP(rootItem);
+
+	return false;
+}
+
+/************************************************************************/
+/*  函数:[4/1/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:不要使用函数AcquireExclusiveAccess来独占设备的访问权限,否则image->ImportFileSystem一直失败(被害一个多星期) ;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CIMAPI2Impl::CreateMediaFileSystem2(void* pdiscfd, TString strVolumeName, IStream** dataStream)
+{
+	if (pdiscfd == NULL)
+		return false;
+
+	IFileSystemImage*		image = NULL;
+	IFileSystemImageResult*	imageResult = NULL;
+	IFsiDirectoryItem*		rootItem = NULL;
+	HRESULT hr = S_FALSE;
+
+	CDiscFormatData *pdiscFormatData = (CDiscFormatData*)pdiscfd;
+	// 获取刻录机设备指针;
+	IDiscRecorder2 *pRecorder2 = NULL;
+	hr = pdiscFormatData->GetInterface()->get_Recorder(&pRecorder2);
+	if (FAILED(hr))
+	{
+		RELEASEP(image);
+		return false;
+	}
+
+	IMAPI_FORMAT2_DATA_MEDIA_STATE iState = IMAPI_FORMAT2_DATA_MEDIA_STATE_UNKNOWN;
+	hr = pdiscFormatData->GetInterface()->get_CurrentMediaStatus(&iState);
+
+	// 获取光盘支持的媒体格式;
+	IMAPI_MEDIA_PHYSICAL_TYPE mediaType = IMAPI_MEDIA_TYPE_UNKNOWN;
+	pdiscFormatData->GetInterface()->get_CurrentPhysicalMediaType(&mediaType);
+
+	// 创建文件系统映像对象;
+	hr = CoCreateInstance(CLSID_MsftFileSystemImage, NULL, CLSCTX_ALL, __uuidof(IFileSystemImage), (void**)&image);
+	if (FAILED(hr))
+	{
+		// 释放;
+		if (image)
+			delete image;
+		image = NULL;
+
+		return false;
+	}
+
+	if (image == NULL)
+		return false;
+
+	hr = image->put_FileSystemsToCreate((FsiFileSystems)(FsiFileSystemJoliet | FsiFileSystemISO9660));
+	if (FAILED(hr))
+	{
+		RELEASEP(image);
+		return false;
+	}
+
+	VARIANT_BOOL vbBlank = VARIANT_FALSE;
+	// 判断光盘是否为空白盘 vbBlank = VARIANT_TRUE则光盘为空白光盘;
+	pdiscFormatData->GetInterface()->get_MediaHeuristicallyBlank(&vbBlank);
+	hr = image->put_FileSystemsToCreate((FsiFileSystems)(FsiFileSystemJoliet | FsiFileSystemISO9660));
+	if (FAILED(hr))
+	{
+		RELEASEP(image);
+		return false;
+	}
+	// 根据光盘的媒体类型来设置文件系统的类型和大小;
+	image->ChooseImageDefaultsForMediaType(mediaType);
+
+	if (vbBlank == VARIANT_TRUE)
+	{// 空白光盘;
+		// 设置文件系统映像的卷名称;
+		hr = image->put_VolumeName(_bstr_t(strVolumeName.c_str()));
+	}
+	else
+	{
+		// 存储光盘多会话;
+		SAFEARRAY *pSafeArrayMulSection = NULL;
+		// 检索光盘的多会话界面;
+		hr = pdiscFormatData->GetInterface()->get_MultisessionInterfaces(&pSafeArrayMulSection);
+		if (!SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			return false;
+		}
+
+		long vale = 0;
+		// 检索下一个可写入操作的位置;
+		hr = pdiscFormatData->GetInterface()->get_NextWritableAddress(&vale);
+		if (SUCCEEDED(hr))
+		{
+			// 将光盘最后一个会话导入到文件系统中;
+			hr = image->put_MultisessionInterfaces(pSafeArrayMulSection);
+			if (!SUCCEEDED(hr))
+			{
+				RELEASEP(image);
+				return FALSE;
+			}
+
+			// 设置光盘之前的数据为已使用(这步是否必须?观VB代码,好像没有这步, 说ImportFileSystem会自动导入光盘的数据);
+			VARIANT *va = NULL;
+			SafeArrayAccessData(pSafeArrayMulSection, (VOID**)&va);
+			if (va)
+			{
+				IMultisession *pMultisession = NULL;
+				pMultisession = (IMultisession*)va[0].pdispVal;
+				hr = pMultisession->put_InUse(VARIANT_TRUE);
+				if (!SUCCEEDED(hr))
+				{
+					SafeArrayDestroy(pSafeArrayMulSection);
+					RELEASEP(image);
+					return FALSE;
+				}
+			}
+
+			//encounter IMAPI_E_IMPORT_SEEK_FAILURE or IMAPI_E_NO_SUPPORTED_FILE_SYSTEM
+			// 导入;
+			FsiFileSystems filesystem;
+			hr = image->ImportFileSystem(&filesystem);
+			if (!SUCCEEDED(hr))
+			{
+				RELEASEP(image);
+				SafeArrayDestroy(pSafeArrayMulSection);
+				return false;
+			}
+		}// get_multisession OK
+		SafeArrayDestroy(pSafeArrayMulSection);
+	}
+
+#if 0 // 判断光盘是否有足够的空间来刻录;
+	LONG lFreeSectorOnMedia = 0;
+	if (SUCCEEDED(hr))
+	{
+		hr = pdiscFormatData->GetInterface()->get_FreeSectorsOnMedia(&lFreeSectorOnMedia);
+		if (SUCCEEDED(hr))
+		{
+			hr = image->put_FreeMediaBlocks(lFreeSectorOnMedia);
+		}
+	}
+
+	// 光盘的每个扇区大小 = 2048 字节;
+	//	image->get_FreeMediaBlocks(&m_nFreeBlock); // 获取光盘的容积
+	ULONGLONG ulDiscSize = (ULONGLONG)lFreeSectorOnMedia * 2048; // 转换成字节数;
+	ULONGLONG ulFileSize = 0;
+	if (ulFileSize > (ulDiscSize - 1024 * 1024))
+	{
+		// 小于1M,无法刻录;
+		return false;
+	}
+#endif
+
+	// 获取文件根对象;
+	hr = image->get_Root(&rootItem);
+	if (!SUCCEEDED(hr))
+	{
+		// 清除...
+		RELEASEP(image);
+		RELEASEP(rootItem);
+		return false;
+	}
+
+	// 添加文件或目录;
+	IFsiItem* pFsiItem = NULL;
+	IStream* fileStream = NULL;
+	IFsiDirectoryItem* pFsiDir = NULL;
+	FsiItemType itemType = FsiItemNotFound;
+	for (vector<DiscPathFile>::iterator it = m_vtDiscItems.begin(); it != m_vtDiscItems.end(); it++)
+	{
+		hr = image->Exists(_bstr_t(it->strDiscPath.c_str()), &itemType);
+		if (SUCCEEDED(hr))
+		{
+			if (itemType == FsiItemNotFound)
+			{// 没有这个目录;
+				hr = image->CreateDirectoryItem(_bstr_t(it->strDiscPath.substr(1).c_str()), &pFsiDir);
+				if (SUCCEEDED(hr))
+				{
+					hr = rootItem->Add(pFsiDir);
+					if (FAILED(hr))
+					{
+						RELEASEP(pFsiDir);
+						continue;
+					}
+				}
+				else {
+					RELEASEP(pFsiDir);
+					continue;
+				}
+			}
+			else if (itemType == FsiItemDirectory)
+			{
+				hr = rootItem->get_Item(_bstr_t(it->strDiscPath.c_str()), &pFsiItem);
+				if (SUCCEEDED(hr))
+				{
+					pFsiDir = (IFsiDirectoryItem*)pFsiItem;
+				}
+				else
+					continue;
+			}
+		}
+		else
+		{
+			RELEASEP(pFsiDir);
+			continue;
+		}
+
+		for (vector<TString>::iterator it_dir = it->vtdirs.begin(); it_dir != it->vtdirs.end(); it_dir++)
+		{
+			hr = pFsiDir->AddTree(_bstr_t(it_dir->c_str()), VARIANT_TRUE);
+			if (FAILED(hr))
+			{
+				OutputDebugString(_T("dfdfdfdfdfdf"));
+			}
+		}
+
+		for (vector<TString>::iterator it_file = it->vtfiles.begin(); it_file != it->vtfiles.end(); it_file++)
+		{
+#ifdef UNICODE
+			hr = SHCreateStreamOnFileEx(it_file->c_str(),
+				STGM_READ | STGM_SHARE_DENY_NONE | STGM_DELETEONRELEASE,
+				FILE_ATTRIBUTE_NORMAL,
+				FALSE,
+				NULL,
+				&fileStream);
+#else
+			wstring strfile;
+			strfile.append((WCHAR*)(convert("GBK", "UCS-2LE", it_file->c_str(), it_file->size()).c_str()), it_file->size());
+			hr = SHCreateStreamOnFileEx(strfile.c_str(),
+				STGM_READ | STGM_SHARE_DENY_NONE | STGM_DELETEONRELEASE,
+				FILE_ATTRIBUTE_NORMAL,
+				FALSE,
+				NULL,
+				&fileStream);
+#endif
+			if (SUCCEEDED(hr))
+			{
+				hr = pFsiDir->AddFile(_bstr_t(it_file->substr(it_file->find_last_of('\\') + 1).c_str()), fileStream);
+			}
+		}
+
+		RELEASEP(pFsiDir);
+	}
+
+	// 生成结果流文件系统;
+	hr = image->CreateResultImage(&imageResult);
+	if (SUCCEEDED(hr))
+	{
+		//
+		// Get the stream
+		//
+		hr = imageResult->get_ImageStream(dataStream);
+		if (SUCCEEDED(hr))
+		{
+			RELEASEP(image);
+			RELEASEP(imageResult);
+			RELEASEP(rootItem);
+			return true;
+		}
+	}
+
+	RELEASEP(image);
+	RELEASEP(imageResult);
+	RELEASEP(rootItem);
+
+	return false;
+}
+
+
+bool CIMAPI2Impl::Initialize()
+{
+	ASSERT(m_pDiscMaster == NULL);
+
+	// 初始化接口IDiscMaster2; 
+	if (m_pDiscMaster == NULL)
+	{
+		m_hResult = CoCreateInstance(__uuidof(MsftDiscMaster2), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiscMaster2), (void**)&m_pDiscMaster);
+		if (!SUCCEEDED(m_hResult))
+		{
+			m_strErrorMsg.Format(_T("Unable to Initialize IDiscMaster2 - Error:0x%08x"), m_hResult);
+			return false;
+		}
+	}
+
+	// 是否包含一个或多个光学设备,并且执行上下文有权访问设备;
+	VARIANT_BOOL isSupported = VARIANT_FALSE;
+	m_hResult = m_pDiscMaster->get_IsSupportedEnvironment(&isSupported);
+	if (!SUCCEEDED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_IsSupportedEnvironment failed! - Error:0x%08x"), m_hResult);
+		return false;
+	}
+
+	if (isSupported == VARIANT_FALSE)
+	{
+		// 没有设备或没有权限访问设备;
+		m_strErrorMsg = _T("There were no writable devices detected!");
+		return false;
+	}
+
+	return true;
+}
+
+int CIMAPI2Impl::GetAvailableDrives()
+{
+	ASSERT(m_pDiscMaster != NULL);
+	if (m_pDiscMaster == NULL)
+		return 0;
+
+	m_vtDevInfo.clear();
+	long totalDevices = 0;
+	// 检索计算机上安装的CD和DVD光盘设备的数量;
+	m_hResult = m_pDiscMaster->get_Count(&totalDevices);
+	if (FAILED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_Count failed! - Error:0x%08x"), m_hResult);
+		return 0;
+	}
+
+	BSTR uniqueID = NULL;
+	for (int i = 0; i < totalDevices; i++)
+	{
+		DeviceInfo devInfo;
+		devInfo.nIndex = i;
+
+		// 检索指定磁盘设备的唯一标识符;
+		m_hResult = m_pDiscMaster->get_Item(i, &uniqueID);
+		if (FAILED(m_hResult))
+			continue;
+
+#ifdef UNICODE
+		devInfo.strDevUId = uniqueID;
+#else
+		_bstr_t uid = uniqueID;
+		devInfo.strDevUId = uid;
+#endif
+
+		// 创建刻录机设备对象;
+		CDiscRecorder* pDiscRecorder = new CDiscRecorder();
+		if (pDiscRecorder == NULL)
+			continue;
+		if (!pDiscRecorder->Initialize(devInfo.strDevUId.c_str()))
+		{
+			delete pDiscRecorder;
+			continue;
+		}
+
+		devInfo.strDevName = pDiscRecorder->GetRecorderName();
+		devInfo.pDevInfo = pDiscRecorder;
+
+		m_vtDevInfo.push_back(devInfo);
+	}
+
+	return totalDevices;
+}
+
+CString CIMAPI2Impl::GetDeviceUniqueID(long nIndex)
+{
+	ASSERT(m_pDiscMaster != NULL);
+
+	BSTR uniqueID = NULL;
+	// 检索指定磁盘设备的唯一标识符;
+	m_hResult = m_pDiscMaster->get_Item(nIndex, &uniqueID);
+	if (FAILED(m_hResult))
+	{
+		m_strErrorMsg.Format(_T("IDiscMaster2->get_Item(%d) failed! - Error:0x%08x"), nIndex, m_hResult);
+		return _T("");
+	}
+
+	return CString((TCHAR*)_bstr_t(uniqueID));
+}
+
+void * CIMAPI2Impl::GetDeivceInfo(int nIndex)
+{
+	if (m_vtDevInfo.size() == 0 || nIndex > m_vtDevInfo.size())
+		return NULL;
+
+	return &m_vtDevInfo.at(nIndex);
+}
+
+void * CIMAPI2Impl::GetDeivceInfo(const TCHAR * pszDevName)
+{
+	for (vector<DeviceInfo>::iterator it = m_vtDevInfo.begin(); it != m_vtDevInfo.end(); it++)
+	{
+		if (_tcscmp(pszDevName, it->strDevName.c_str()) == 0)
+		{
+			return &(*it);//或return &m_vtDevInfo.at(it - m_vtDevInfo.begin());
+		}
+	}
+
+	return NULL;
+}
+
+void CIMAPI2Impl::AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles)
+{
+	if (strFatherNode.size() == 0)
+		strFatherNode = _T("/");
+	else if (strFatherNode.at(0) != _T('\\') && strFatherNode.at(0) != _T('/'))
+	{
+		strFatherNode.insert(0, _T("/"));
+	}
+
+	DiscPathFile *pdisc = NULL;
+	bool IsDiscPathExists = false;
+	for (vector<DiscPathFile>::iterator it = m_vtDiscItems.begin(); it != m_vtDiscItems.end(); it++)
+	{
+		if (_tcsicmp(strFatherNode.c_str(), it->strDiscPath.c_str()) == 0)
+		{
+			pdisc = &(*it);
+			IsDiscPathExists = true;
+			break;
+		}
+	}
+
+	if (!IsDiscPathExists)
+	{
+		DiscPathFile discpath;
+		discpath.strDiscPath = strFatherNode;
+		discpath.vtfiles.assign(vtfiles.begin(), vtfiles.end());
+		m_vtDiscItems.push_back(discpath);
+	}
+	else {
+		pdisc->vtfiles.insert(pdisc->vtfiles.end(), vtfiles.begin(), vtfiles.end());
+		// 去重复前,必须排序;
+		sort(pdisc->vtfiles.begin(), pdisc->vtfiles.end());
+		// 去重复;//vector<DiscPathFile>::iterator end_unique =  unique(pdisc->vtfiles.begin(), pdisc->vtfiles.end()); 
+		pdisc->vtfiles.erase(unique(pdisc->vtfiles.begin(), pdisc->vtfiles.end()), pdisc->vtfiles.end());
+	}
+}
+
+void CIMAPI2Impl::AddFolder2Disc(TString strFatherNode, TString strFolder)
+{
+	if (strFatherNode.size() == 0)
+		strFatherNode = _T("/");
+	else if (strFatherNode.at(0) != _T('\\') && strFatherNode.at(0) != _T('/'))
+	{
+		strFatherNode.insert(0, _T("/"));
+	}
+
+	DiscPathFile *pdisc = NULL;
+	bool IsDiscPathExists = false;
+	for (vector<DiscPathFile>::iterator it = m_vtDiscItems.begin(); it != m_vtDiscItems.end(); it++)
+	{
+		if (_tcsicmp(strFatherNode.c_str(), it->strDiscPath.c_str()) == 0)
+		{
+			pdisc = &(*it);
+			IsDiscPathExists = true;
+			break;
+		}
+	}
+
+	if (!IsDiscPathExists)
+	{
+		DiscPathFile discpath;
+		discpath.strDiscPath = strFatherNode;
+		discpath.vtdirs.push_back(strFolder);
+		m_vtDiscItems.push_back(discpath);
+	}
+	else
+	{
+		IsDiscPathExists = false;
+		for (vector<TString>::iterator it = pdisc->vtdirs.begin(); it != pdisc->vtdirs.end(); it++)
+		{
+			if (_tcsicmp(strFolder.c_str(), it->c_str()) == 0)
+			{
+				IsDiscPathExists = true;
+				break;
+			}
+		}
+
+		if (!IsDiscPathExists)
+			pdisc->vtdirs.push_back(strFolder);
+	}
+}
+
+bool CIMAPI2Impl::BurnMedia(int nIndex, TString strArtist, TString strTitle)
+{
+	// 创建刻录机设备对象;
+	CDiscRecorder* pDiscRecorder = new CDiscRecorder();
+	if (pDiscRecorder == NULL)
+		return false;
+
+	if (!pDiscRecorder->Initialize(GetDeviceUniqueID(nIndex)))
+	{
+		delete pDiscRecorder;
+		return false;
+	}
+
+	CDiscFormatData discFormatData;
+	if (discFormatData.Initialize(pDiscRecorder, _T("IMAPI2-BurnCD")))
+	{
+		// 获取当前媒体的大小;
+		LONG ulCapity;
+		discFormatData.GetFreeSectorsOnMedia(ulCapity);
+
+		//
+		// Create the file system
+		//
+		IStream* dataStream = NULL;
+		if (!CreateMediaFileSystem(&discFormatData, strTitle, &dataStream))
+		{	// CreateMediaFileSystem reported error to UI
+			return false;
+		}
+
+		discFormatData.SetCloseMedia(false);
+
+		//
+		// Burn the data, this does all the work
+		//
+		discFormatData.Burn(CIMAPI2Impl::m_pDailog == NULL ? 0 : CIMAPI2Impl::m_pDailog->m_hWnd, dataStream);
+
+		//
+		// Release the IStream after burning
+		//
+		dataStream->Release();
+
+		//
+		// Eject Media if they chose
+		//
+		if (false)
+		{
+			pDiscRecorder->EjectMedia();
+		}
+	}
+
+	if (pDiscRecorder)
+		delete pDiscRecorder;
+
+	return false;
+}
+
+void CIMAPI2Impl::EraseMedia(int nIndex)
+{
+}
+
+bool CIMAPI2Impl::SetWriteSpeed(ULONG nIndex)
+{
+	return false;
+}
+

+ 86 - 0
Burndiscs/Burndiscs/IMAPI2Impl.h

@@ -0,0 +1,86 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/22/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __IMAPI2_IMPL__
+#define __IMAPI2_IMPL__
+
+#pragma once
+#include "IBurndisc.h"
+
+class CIMAPI2Impl : public IBurndisc
+{
+	volatile LONG	m_nRef;
+	IDiscMaster2	*m_pDiscMaster;
+	HRESULT			m_hResult;
+	CString			m_strErrorMsg;
+	std::vector<DeviceInfo>		m_vtDevInfo;
+
+	typedef struct __DISCPATHFILE__ {
+		TString strDiscPath;
+		vector<TString> vtfiles;
+		vector<TString> vtdirs;
+	}DiscPathFile, *pDiscPathFile;
+
+	vector<DiscPathFile> m_vtDiscItems;
+public:
+	CIMAPI2Impl(void);
+	~CIMAPI2Impl(void);
+
+	static CDialog* m_pDailog;
+
+	virtual ULONG STDMETHODCALLTYPE AddRef();
+	virtual ULONG STDMETHODCALLTYPE Release();
+	//virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void **ppvObject);
+	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __RPC__deref_out void **ppvObject);
+
+protected:
+	bool CreateMediaFileSystem(void* pdiscfd, TString strVolumeName, IStream** dataStream);
+	bool CreateMediaFileSystem2(void* pdiscfd, TString strVolumeName, IStream** dataStream);
+
+public:
+	bool Initialize();
+	int GetAvailableDrives();
+	CString GetDeviceUniqueID(long nIndex);
+	void* GetDeivceInfo(int nIndex);
+	void* GetDeivceInfo(const TCHAR *pszDevName);
+	void AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles);
+	void AddFolder2Disc(TString strFatherNode, TString strFolder);
+	bool BurnMedia(int nIndex, TString strArtist, TString strTitle);
+	void EraseMedia(int nIndex);
+	bool SetWriteSpeed(ULONG nIndex);
+	void 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
+	) {};
+	void IMAPI2Set(void* pDailog) {
+		CIMAPI2Impl::m_pDailog = (CDialog*)pDailog;
+	};
+};
+
+#endif

+ 27 - 0
Burndiscs/Burndiscs/Nero.h

@@ -0,0 +1,27 @@
+#ifndef __NERO__
+#define __NERO__
+
+#include "NeroAPIGlue.h"
+#define NERO_WAITCD_TEXTS
+#include "NeroUserDialog.h"
+#undef NERO_WAITCD_TEXTS
+
+/* for the settings */
+typedef BOOL(NERO_CALLBACK_ATTR *IdleCallback) (void *pUserData);
+typedef NeroUserDlgInOut(NERO_CALLBACK_ATTR *UserDialog)(void *pUserData, NeroUserDlgInOut type, void *data);
+
+/* for the progress display */
+typedef BOOL(NERO_CALLBACK_ATTR *ProgressCallback) (void *pUserData, DWORD dwProgressInPercent);
+typedef BOOL(NERO_CALLBACK_ATTR *AbortedCallback)(void *pUserData);
+typedef void (NERO_CALLBACK_ATTR *AddLogLine)(void *pUserData, NERO_TEXT_TYPE type, const char *text);
+typedef void (NERO_CALLBACK_ATTR *SetPhaseCallback)(void *pUserData, const char *text);
+typedef void (NERO_CALLBACK_ATTR *DisableAbortCallback)(void *pUserData, BOOL abortEnabled);
+typedef void (NERO_CALLBACK_ATTR *SetMajorPhaseCallback)(void *pUserData, NERO_MAJOR_PHASE phase, void *reserved);
+
+/* IO callbacks - both take a FILE * as user data */
+typedef DWORD(NERO_CALLBACK_ATTR *WriteIOCallback)(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+typedef DWORD(NERO_CALLBACK_ATTR *ReadIOCallback)(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+typedef BOOL(NERO_CALLBACK_ATTR  *EOFCallback)(void *pUserData);
+typedef BOOL(NERO_CALLBACK_ATTR  *ErrorCallback)(void *pUserData);
+
+#endif

+ 113 - 0
Burndiscs/Burndiscs/Nero/Include/APIRoboControl.h

@@ -0,0 +1,113 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: APIRoboControl.h
+|*
+|* PURPOSE: Robo handling for NeroAPI
+******************************************************************************/
+#ifndef APIROBOCONTROL_H
+#define APIROBOCONTROL_H
+
+/* This file is responsible for associating Robos with drives etc.
+ * You can associate a Robo with a drive by using NeroAssociateRobo()
+ * with a device handle of a recorder */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "NeroAPI.h"
+
+typedef enum
+{
+   NCT_PORT_SERIAL,
+     NCT_PORT_PARALLEL,
+     NCT_PORT_USB
+}
+NERO_COMMNODE_TYPE;
+
+typedef enum
+{
+   NEROAPI_ROBO_OK=0,
+     NEROAPI_ROBO_NOTFOUND=1,
+	 NEROAPI_ROBO_NOTSUPPORTED=2
+}
+NEROAPI_ROBO_ERROR;
+
+/* Callback for label printing. Will be called by NeroAPI when it
+ * is time to print the label. Must return TRUE if label was printed
+ * sucessfully, FALSE otherwise. 
+ * This callback is called from *within* the NeroRobo driver thread
+ * so no GUI interaction is usually allowed (spawning a new process is
+ * ok, though). 
+ * This callback mustn't return until the print job is done */
+typedef BOOL(*NeroPrintLabelCallback_t)(void *data);
+
+typedef struct
+{
+   char  nrdiIdentifier[256];
+   DWORD nrdiVersionNumber;
+   char  nrdiDLLName[256];
+} NERO_ROBO_DRIVER_INFO;
+
+typedef struct
+{
+   DWORD nrdisNumDevInfos; /* number of following entries */
+   NERO_ROBO_DRIVER_INFO nrdiDevInfos[1];
+} NERO_ROBO_DRIVER_INFOS;
+
+
+
+NEROAPI_API NERO_ROBO_DRIVER_INFOS * NADLL_ATTR NeroGetAvailableRoboDrivers();
+
+/* associate a robo of specified type connected to specified port
+ * with a device handle.
+ * For now, this function will always return NEROAPI_ROBO_OK
+ * as it doesn't actually do anything with the robo.
+ * You can pass NULL instead of a printcallback in which case
+ * printing will be disabled */
+NEROAPI_API NEROAPI_ROBO_ERROR NADLL_ATTR NeroAssociateRobo(NERO_DEVICEHANDLE aDeviceHandle,	
+						 const char *robo_identifier,
+						 NERO_COMMNODE_TYPE port,
+						 int portnum,
+						 NeroPrintLabelCallback_t printcallback,
+						 void *printcallback_data);
+
+/* The following declarations describe an interface to set runtime options for the robo,
+ * that is settings the robo won't remember over sessions. With this interface, the generic
+ * control flow of the robo can be set. The function below will return NEROAPI_ROBO_NOTSUPPORTED
+ * if a specific control flow option is not supported by the robo or otherwise not available */
+
+typedef enum
+{
+	NERO_ROBO_FLAG_CLEANUP,// set this to TRUE in order to have the Robo cleanup itself
+		                   // like removing any remaining CDs from the trays etc.
+						   // Note that the resulting behaviour may sometimes look like a bad 
+						   // control flow (the robo will try to remove CDs where there aren't
+						   // any and so on). So you shouldn't use this option unless you're
+						   // cleaning up after a hard server crash or have another good reason
+						   // to do so
+	NERO_ROBO_INSERTCD_RETRIES // This flag specifies how often Nero is to try to insert another
+							   // CD from the input tray if the CD in the drive is unwritable
+							   // The current default value for the number of retries is 5,
+							   // a value of 0 means to try indefinitely
+} NERO_ROBO_FLAG;
+
+NEROAPI_API NEROAPI_ROBO_ERROR NADLL_ATTR NeroSetRoboFlag(NERO_DEVICEHANDLE aDeviceHandle,
+														  NERO_ROBO_FLAG  eRoboFlag,
+														  int iRoboValue);
+
+																	   
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // APIROBOCONTROL_H

+ 1794 - 0
Burndiscs/Burndiscs/Nero/Include/NeroAPI.h

@@ -0,0 +1,1794 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroAPI.h
+|*
+|* PURPOSE: Main interface for Nero API DLL
+******************************************************************************/
+#ifndef _NEROAPI_
+#define _NEROAPI_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+   
+/*
+// If included within the glue code, then don't add special
+// attributes to the functions.
+*/
+#define NADLL_ATTR  __cdecl
+#ifdef __NEROAPIGLUE__
+	#define NEROAPI_API
+#else
+
+	/* NEROAPI must not be defined when using the DLL */
+	#ifdef NEROAPI
+		#define NEROAPI_API __declspec(dllexport)
+	#else
+		#define NEROAPI_API __declspec(dllimport)
+	#endif /* NEROAPI */
+
+#endif /* __NEROAPIGLUE__ */
+
+#ifdef  __cplusplus
+class CSourceDriveInfo;
+typedef CSourceDriveInfo *NERO_DEVICEHANDLE;
+#else
+typedef void *NERO_DEVICEHANDLE;
+#endif
+
+
+#include <windows.h> // the data types used below are those of windows
+   
+#include <time.h>
+
+#include "NeroUserDialog.h"
+
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+
+/*
+// The NeroAPI never uses static memory. Instead, memory is allocated
+// dynamically on behalf of the application, e.g. for strings. This
+// memory has to be freed with this function.
+//
+// Passing a NULL is allowed.
+*/
+NEROAPI_API void NADLL_ATTR NeroFreeMem (void *pMem);
+
+
+/*
+// All functions returning an DWORD will return 0 for success and a
+// error number otherwise. This error numbers are opaque and neither
+// can nor should be interpreted by the application. Instead, localized
+// strings are provided for errors and informative displays.
+//
+// The NeroAPI keeps a log of such informative messages or errors.
+
+// In case of an error, NeroGetLastError() will return more information
+// about the last error and NeroGetErrorLog() will show all recorded
+// events.
+//
+// Both functions return NULL if no error is available.
+//
+// Memory is allocated for the string, which has to be freed with NeroFreeMem().
+//
+// Note: NeroCloseDrive() has to throw away all errors, because they 
+//       might be bound to the driver. Handle errors before calling it!
+*/
+NEROAPI_API char * NADLL_ATTR NeroGetLastError ();
+NEROAPI_API char * NADLL_ATTR NeroGetErrorLog ();
+
+/* NeroAPI >= 6.0.0.29: returns the last iNum errors */
+NEROAPI_API char * NADLL_ATTR NeroGetLastErrors(int iNum, DWORD dwFlags, void *reserved);
+
+/* include also errors which does not contain a description to be shown in the GUI */
+#define NGLE_ALL (1<<0) 
+/* format the errors as in the NeroAPI error log */
+#define NGLE_REPORT (1<<1) 
+
+
+
+/*
+// NeroAPI >= 6.0.0.0:
+// Error code describing an error happened during communication with a drive.
+// This error code is returned by NeroIsDeviceReady. Other functions set an internal error
+// variable to one of these codes if an error occured. This error can be received with
+// NeroGetLastDriveError.
+*/
+typedef enum
+{
+   NDE_NO_ERROR  = 0, // no error occured/ drive is ready
+   NDE_GENERIC_ERROR = 1, // generic error, not handled with other enums
+   NDE_DRIVE_IN_USE = 2, // drive cannot be locked, maybe a other application uses this drive at the moment
+   NDE_DRIVE_NOT_READY = 3, // drive is not ready
+   NDE_NO_DRIVE = 4, // The given device is not available . Probably removed by the user (USB/Firewire)
+   NDE_DISC_NOT_PRESENT = 5, // no medium in drive, status of tray unknown
+   NDE_DISC_NOT_PRESENT_TRAY_OPEN = 6, // no medium - tray open
+   NDE_DISC_NOT_PRESENT_TRAY_CLOSED = 7 // no medium - tray closed
+} NERO_DRIVE_ERROR;
+
+// Check for all variations of 'disc not present'
+#define DISC_NOT_PRESENT(x)	(((x == NDE_DISC_NOT_PRESENT) || \
+								  (x == NDE_DISC_NOT_PRESENT_TRAY_CLOSED) || \
+								  (x == NDE_DISC_NOT_PRESENT_TRAY_OPEN)) ? TRUE : FALSE)
+
+/*
+// NeroAPI >= 6.0.0.0:
+// get the last error occured during communication with a drive
+// 
+// The following methods set this error value:
+//  - NeroGetCDInfo
+//  - NeroImportDataTrack
+//  - NeroEjectLoadCD
+//  - NeroGetCDRWErasingTime
+//  - NeroEraseDisc
+//
+// All these methods first reset the error value and if an error occured the value is set
+// accordingly.
+*/
+NEROAPI_API void NADLL_ATTR NeroGetLastDriveError( NERO_DRIVE_ERROR *driveError, void *reserved);
+
+
+/*
+// Clear errors and log (done automatically for every read or write function,
+// but can be used to avoid false memory leak warnings).
+*/
+NEROAPI_API void NADLL_ATTR NeroClearErrors ();
+
+
+/*
+// Version management for this API:
+*/
+
+// This file is the interface for this version of NeroAPI
+#define NEROAPI_VERSION_MAJOR_HIGH		7
+#define NEROAPI_VERSION_MAJOR_LOW		0
+#define NEROAPI_VERSION_MINOR_HIGH		5
+#define NEROAPI_VERSION_MINOR_LOW		6
+
+/* Fills the pointed numbers with version number and returns true for 
+   success. Extended in NeroAPI 5.5.9.9 to support multiple digits */
+NEROAPI_API BOOL NADLL_ATTR NeroGetAPIVersionEx(WORD *majhi
+											   ,WORD *majlo
+											   ,WORD *minhi
+											   ,WORD *minlo
+											   ,void *reserved);  // Must be NULL
+
+/* Using this function, an application can tell NeroAPI for which version of NeroAPI it was
+designed to work. NeroAPI will then tries to behave as this version as much as possible. This
+ensures the binary compatibility with future versions of NeroAPI. If this function is not called,
+NeroAPI will behaves as NeroAPI 5.0.3.9. If your application uses NeroAPIGlue.c, this function
+will be automatically called. Extended in NeroAPI 5.5.9.9 to support multiple digits 
+
+If pPrevExpectedVersion is not NULL, it must point onto an array of 4 WORDs that will be filled
+with the previously expected version number
+
+Returns true for success*/
+NEROAPI_API BOOL NADLL_ATTR NeroSetExpectedAPIVersionEx(WORD majhi
+                                                       ,WORD majlo
+													   ,WORD minhi
+													   ,WORD minlo
+													   ,WORD *pPrevExpectedVersion);
+
+/*
+// During writing or in several long running functions control
+// is transfered to the DLL. The application has to provide services
+// and dialog with the user via callback functions.
+//
+// NERO_CALLBACK_ATTR is defined in "NeroUserDialog.h" and ensures that
+// the same conventions are used for passing of parameters.
+*/
+typedef struct tag_NERO_CALLBACK
+{
+	void *ncCallbackFunction; /* actually, this is a pointer to one of several different callback functions defined below */
+	void *ncUserData;         /* this will be passed to the function as first parameter */
+} NERO_CALLBACK;
+
+typedef BOOL (NERO_CALLBACK_ATTR *NERO_IDLE_CALLBACK) (void *pUserData); /* called regularly during long running activities; return TRUE if this activity shall be aborted */
+
+
+/*
+// The NeroAPI needs some information:
+*/
+typedef struct tag_NERO_SETTINGS
+{
+	const char *nstNeroFilesPath;   /* directory name with trailing '\' of where to find the additional Nero DLL and text files */
+   
+	const char *nstVendor,
+		*nstSoftware;               /* path for registry settings (use "ahead", "Nero - Burning Rom" for Nero application's settings) */
+	const char *nstLanguageFile;    /* name of the Nero language file; relativ to nstNeroFilesPath (e.g. "Nero.txt") */
+	NERO_CALLBACK nstIdle;          /* NERO_IDLE_CALLBACK, may be NULL */
+	NERO_CALLBACK nstUserDialog;    /* NERO_USER_DIALOG, must not be NULL, see "NeroUserDialog.h" for details */
+
+	/*
+	// overburn settings:
+	// overburning (writing more than the nominal capacity of a disc) is allowed if:
+	//  - nstEnableOverburn == TRUE
+	//  - nstOverburnSize >= amount of required blocks for compilation
+	// and if
+	//  - the drive supports it
+	//  - DAO is used.
+	// Even then, overburning has to be acknowledged via callback (see DLG_OVERBURN in "NeroUserDialog.h").
+	*/
+	BOOL  nstEnableOverburn;
+	DWORD nstOverburnSize;    /* in blocks */
+} NERO_SETTINGS;
+
+
+/*
+// Initialize the DLL. Must be successful before any of the remaining
+// functions can be called. Settings structure and strings it points
+// to are _not_ copied and function callbacks must be available all
+// the time.
+*/
+
+typedef enum
+{
+	NEROAPI_INIT_OK=0,
+	NEROAPI_INIT_INVALID_ARGS,
+	NEROAPI_INIT_UNSPECIFIED_ERROR,					// Unspecified error
+	NEROAPI_INIT_INVALID_SERIAL_NUM,
+	NEROAPI_INIT_DEMOVERSION_EXPIRED,
+	NEROAPI_INIT_ALREADY_INITIALISED,				
+	NEROAPI_INIT_CANNOT_LOCK						
+} NEROAPI_INIT_ERROR;
+
+// Make sure to keep *all* the data including the strings valid as long as you're using NeroAPI,
+// since Nero will only store a pointer to this structure, not make a copy.
+NEROAPI_API NEROAPI_INIT_ERROR NADLL_ATTR NeroInit (const NERO_SETTINGS *pNeroSettings,const char *reserved);
+
+
+/*
+// Call this function before closing the DLL. This is necessary because
+// some clean-up actions like stopping threads cannot be done in the
+// close function of the DLL.
+//
+// NeroDone returns TRUE if some memory blocks were not unallocated using NeroFreeMem. They are dumped in
+// the debug output.
+// NeroDone returns FALSE if it succeeded
+*/
+NEROAPI_API BOOL NADLL_ATTR NeroDone ();
+
+/*
+Call this function to change a global option of NeroAPI
+*/
+
+typedef enum
+{
+	NEROAPI_OPTION_MSG_FILE_NAME,		// Set the language file. The value points to a string containing the file name. This adress will be kept.
+	NEROAPI_OPTION_WRITE_BUFFER_SIZE,	// Set write buffer size. Value points onto an integer containing the size in byte
+	
+	// NeroAPI>=6.0.0.0 Set the user dialog callback, overwriting nstUserDialog of the settings
+	// structure passed to NeroInit. 
+	// Pass a pointer to a NERO_CALLBACK structure as value. After returning,
+	// the struct will contain the previous user callback.
+	NEROAPI_OPTION_USER_DLG_CALLBACK,		
+	// NeroAPI>=6.0.0.0 Set the idle callback, overwriting nstIdle of the settings
+	// structure passed to NeroInit. 
+	// Pass a pointer to a NERO_CALLBACK structure as value. After returning,
+	// the struct will contain the previous idle callback.
+	NEROAPI_OPTION_IDLE_CALLBACK,
+
+	// NeroAPI>=6.0.0.27: Enable/Disable overburning for CDs.
+	// Value is a pointer to a DWORD containing the overburn size (the total size
+	// of the CD) in blocks.
+	// If the value is NULL, disable overburning for CDs.
+	NEROAPI_OPTION_OVERBURN,
+
+	// NeroAPI>=6.3.1.12: Enable/Disable overburning for DVD.
+	// Value is a pointer to a DWORD containing the overburn size (the total size
+	// of the DVD) in blocks. 
+	// If the value is NULL, disable overburning for DVDs.
+	NEROAPI_OPTION_DVDOVERBURN,
+
+	// NeroAPI>=6.6.0.4: Enable/Disable volume labels burned as 16 bit unicode
+	// for DVD-Video compatible compilations. Normally, this violates
+	// the DVD-Video specification. However, some applications might want to
+	// enable it anyway. If this option is disabled, NeroAPI will convert
+	// characters that are not DVD-Video compatible to '_'.
+	// If value is NULL, 16 bit unicode volume label is disabled, otherwise enabled.
+	NEROAPI_OPTION_ALLOW_16BITUNICODE_DVDVIDEO_VOLUMELABEL
+
+} NEROAPI_OPTION;
+
+NEROAPI_API int NADLL_ATTR NeroSetOption(NEROAPI_OPTION option,void *value);
+
+
+/*
+// Code to scan the SCSI/IDE bus and get information about
+// the available WORM/CDROM drives:
+*/
+
+typedef enum
+{       
+	NEA_SCSI_DEVTYPE_UNKNOWN,
+	NEA_SCSI_DEVTYPE_WORM,      /* can write */
+	NEA_SCSI_DEVTYPE_CDROM,     /* can only read */
+	NEA_SCSI_DEVTYPE_UNSUPPORTED_WORM	/* can write but is not supported by NeroAPI */
+} NEROAPI_SCSI_DEVTYPE;
+
+typedef struct tag_NERO_SPEED_INFOS
+{
+	DWORD nsiNumSupportedSpeeds;     /* 1 if the speed cannot be changed */
+	DWORD nsiBaseSpeedKBs;			 /* Speed corresponding to 1X for the selected media in KB/s */
+	DWORD nsiSupportedSpeedsKBs[64]; /* List of possible speeds in KB/s */
+	DWORD nsiSupportedSpeeds[64];    /* List of possible speeds in multiple of 150KB/s (1X for CD) (present for compatibility) */
+	DWORD nsiReserved[32];
+} NERO_SPEED_INFOS;
+
+typedef enum tag_NERO_MEDIA_TYPE
+{
+	MEDIA_NONE				=	0,								// No media present (NeroAPI>=5.5.9.4)
+	MEDIA_CD				=	0x00001,						// CD-R/RW
+	MEDIA_DDCD				=	0x00002,						// DDCD-R/RW
+	MEDIA_DVD_M				=	0x00004,						// DVD-R/RW
+	MEDIA_DVD_P				=	0x00008,						// DVD+RW
+	MEDIA_DVD_RAM			=	0x00010,						// DVD-RAM
+	MEDIA_ML				=	0x00020,						// ML (Multi Level disc)
+	MEDIA_MRW				=	0x00040,						// Mt. Rainier
+
+	//NeroAPI>=5.5.9.4:
+	MEDIA_NO_CDR			=	0x00080,						// Exclude CD-R
+	MEDIA_NO_CDRW			=	0x00100,						// Exclude CD-RW
+	MEDIA_CDRW				=   MEDIA_CD|MEDIA_NO_CDR,			// CD-RW		
+	MEDIA_CDR				=   MEDIA_CD|MEDIA_NO_CDRW,			// CD-R
+	MEDIA_DVD_ROM			=	0x00200,						// DVD-ROM (non writable)
+	MEDIA_CDROM				=	0x00400,						// CD-ROM (non writable)
+
+	//NeroAPI>=5.5.9.10
+	MEDIA_NO_DVD_M_RW		=	0x00800,						// Exclude DVD-RW
+	MEDIA_NO_DVD_M_R		=	0x01000,						// Exclude DVD-R
+	MEDIA_NO_DVD_P_RW		=	0x02000,						// Exclude DVD+RW
+	MEDIA_NO_DVD_P_R		=	0x04000,						// Exclude DVD+R
+	MEDIA_DVD_M_R			=	MEDIA_DVD_M|MEDIA_NO_DVD_M_RW,	// DVD-R
+	MEDIA_DVD_M_RW			=	MEDIA_DVD_M|MEDIA_NO_DVD_M_R,	// DVD-RW
+	MEDIA_DVD_P_R			=	MEDIA_DVD_P|MEDIA_NO_DVD_P_RW,	// DVD+R
+	MEDIA_DVD_P_RW			=	MEDIA_DVD_P|MEDIA_NO_DVD_P_R,	// DVD+RW
+	MEDIA_FPACKET			=   0x08000,						// Fixed Packetwriting
+	MEDIA_VPACKET			=	0x10000,						// Variable Packetwriting
+	MEDIA_PACKETW			=	MEDIA_MRW|MEDIA_FPACKET			// a bit mask for packetwriting
+									|MEDIA_VPACKET,
+	//NeroAPI>=5.5.10.4
+	MEDIA_HDB				=	0x20000,						// HD-Burn
+
+	//NeroAPI>=6.0.0.29
+	MEDIA_DVD_P_R9			=	0x40000,						// DVD+R Double Layer 9GB
+	//NeroAPI>=6.6.0.8
+	MEDIA_DVD_M_R9			=	0x80000,						// DVD-R Dual Layer 9GB
+	MEDIA_DVD_ANY_R9		=	MEDIA_DVD_P_R9|MEDIA_DVD_M_R9,	// Any DVD Dual/Double Layer 9GB
+	MEDIA_DVD_ANY			=	MEDIA_DVD_M|MEDIA_DVD_P|MEDIA_DVD_RAM|MEDIA_DVD_ANY_R9, // Any DVD-Media
+
+	//NeroAPI>=6.6.0.8
+	MEDIA_BD_ROM			=	0x100000,						// Blu-ray Disc ROM
+	MEDIA_BD_R				=	0x200000,						// Blu-ray Disc Recordable
+	MEDIA_BD_RE				=	0x400000,						// Blu-ray Disc Rewritable
+	MEDIA_BD				=	MEDIA_BD_R | MEDIA_BD_RE,		// Any recordable Blu-ray Disc media
+	MEDIA_BD_ANY			=	MEDIA_BD|MEDIA_BD_ROM,			// Any Blu-ray Disc media
+
+	//NeroAPI>=6.6.0.1001
+	MEDIA_HD_DVD_ROM		=	0x0800000,						// HD DVD ROM
+	MEDIA_HD_DVD_R			=	0x1000000,						// HD DVD Recordable
+	MEDIA_HD_DVD_RW			=	0x2000000,						// HD DVD Rewritable
+	MEDIA_HD_DVD			=	MEDIA_HD_DVD_R|MEDIA_HD_DVD_RW,	// Any recordable HD DVD media
+	MEDIA_HD_DVD_ANY		=	MEDIA_HD_DVD|MEDIA_HD_DVD_ROM,	// Any HD DVD media
+} NERO_MEDIA_TYPE;
+
+typedef DWORD NERO_MEDIA_SET;	// Represents a set of several medias
+
+typedef struct tag_NERO_SCSI_DEVICE_INFO
+{
+	char                nsdiDeviceName[64];
+	char                nsdiHostAdapterName[4];
+    char                *nsdiLongHostAdapterName;	/* NeroAPI >= 6.6.0.10: Unlimited host adapter name */
+													/* Adapter names can be more than 8 chars, therefore we define a pointer */
+													/* that has to be freed afterwards with NeroFreeMem. */
+													/* This pointer will be filled only if specific option is passed to */
+													/* NeroGetAvailableDevicesEx(), and the 'old' field will be then zeroed. */
+	DWORD               nsdiHostAdapterNo; 
+	DWORD               nsdiDeviceID;
+	NEROAPI_SCSI_DEVTYPE nsdiDevType;
+	char                nsdiDriveLetter;        /* Windows drive letter or 0 if not available */
+
+	DWORD				nsdiCapabilities;       /* drive capabilities: */
+#define NSDI_ALLOWED				(1<<0)      /* the drive can only be used if this bit is set */
+#define NSDI_DAO                    (1<<1)      /* can write in DAO. */
+#define NSDI_READ_CD_TEXT           (1<<2)      /* can read CD text */
+#define NSDI_VARIABLE_PAUSES_IN_TAO (1<<3)      /* see natPauseInBlksBeforeThisTrack below */
+#define NSDI_DAO_WRITE_CD_TEXT      (1<<4)      /* writes CD text in DAO (see natArtist/Title); never supported in TAO */
+#define NSDI_IMAGE_RECORDER			(1<<6)		/* drive is the image recorder */
+#define NSDI_UNDETECTED				(1<<7)
+#define NSDI_IDE_BUS				(1<<8)
+#define NSDI_SCSI_BUS				(1<<9)
+#define NSDI_BUF_UNDERRUN_PROT		(1<<10)		/* drive has a buffer underrun protection feature (not necessary Burn Proof) */
+#define NSDI_RESERVED				(1<<11)		/* Must not be used */
+#define NSDI_RESERVED2				(1<<12)		/* Must not be used */
+#define NSDI_ALLOW_CHANGE_BOOKTYPE	(1<<13)		/* NeroAPI >5.5.10.7: DVD recorder can change booktype of burned medium */
+#define NSDI_DVDPLUSVR_SUPPORTED    (1<<14)     /* NeroAPI >= 6.0.0.0: This recorder can write DVD+VR */
+#define NSDI_OVERBURN_SUPPORTED     (1<<15)     /* NeroAPI >= 6.6.0.10: The device supports overburn. */
+#define NSDI_RESERVED3              (1<<16)     /* Must not be used */
+#define NSDI_BURN_30MM_AT_LEAST     (1<<17)     /* NeroAPI >= 6.6.1.0: Device can burn 30mm at least to be compatible with dvd-rom */
+#define NSDI_RESERVED4              (1<<18)     /* Must not be used */
+#define NSDI_ULTRARAW_96            (1<<19)     /* NeroAPI >= 6.6.1.0: Device UltraRaw 96 support */  
+#define NSDI_RESERVED5              (1<<20)     /* Must not be used */
+
+	NERO_SPEED_INFOS    nsdiReadSpeeds;
+	NERO_SPEED_INFOS    nsdiWriteSpeeds;
+	const void         *nsdiDriver;             /* opaque identifier of the internal driver, required by NeroOpenDevice() */
+	char		nsdiBufUnderrunProtName[64];	/* Buffer underrun protection technology name */
+												/* The string will be empty if the technology has no name */
+	DWORD				nsdiMandatoryBUPSpeed;	/* it is highly recommanded to enable buffer
+												   underrun protection protection when burning at this speed or
+												   faster. Contains 0 if there is no recommandation */
+	NERO_MEDIA_SET		nsdiMediaSupport;		/* NeroAPI>=5.5.4.1: Bit field of supported writable media (constructed with the NERO_MEDIA_TYPE enum)*/
+
+	DWORD				nsdiDriveBufferSize;	/* NeroAPI>=5.5.9.4: Drive buffer size (internal) in KB */
+	
+	DWORD				nsdiDriveError;			/* NeroAPI>=6.0.0.0: Contains a NERO_DRIVE_ERROR that occured during generating the information.
+												   If != NDE_NO_ERROR, some information like the drive capabilities or the speeds might be wrong.
+												   You can check with NeroIsDeviceReady if the drive is ready later
+												   and update the device information with NeroUpdateDeviceInfo.
+												   NDE_DISC_NOT_PRESENT* errors can be ignored.
+												*/
+	NERO_MEDIA_SET		nsdiMediaReadSupport;	/* NeroAPI>=6.0.0.8: Bit field of supported readable media (constructed with the NERO_MEDIA_TYPE enum)*/
+	char				nsdiFirmwareRevision[8];/* NeroAPI >= 6.6.0.10: Firmware Revision of the device. Not less than 4 chars, but with a \0 trailing char. */
+
+	DWORD               nsdiReserved[59];       /* Should be zero */
+} NERO_SCSI_DEVICE_INFO;
+
+typedef struct tag_NERO_SCSI_DEVICE_INFOS
+{
+	DWORD nsdisNumDevInfos; /* number of the following entries */
+	NERO_SCSI_DEVICE_INFO nsdisDevInfos[1];
+} NERO_SCSI_DEVICE_INFOS;
+
+/* Gets a list of available WORM and CDROM devices, free with NeroFreeMem(). */
+/* Returns NULL for error */
+NEROAPI_API NERO_SCSI_DEVICE_INFOS * NADLL_ATTR NeroGetAvailableDrivesEx(
+													NERO_MEDIA_TYPE	mediaType,	// Provide speeds values for this kind of media
+													DWORD dwFlags);		        // NeroAPI >= 6.6.0.10: See below for values available
+#define NGADE_GET_LONG_HOST_ADAPTER_NAMES        (1<<0) /* NeroAPI >= 6.6.0.10: Provides long host adapter names. nsdiLongHostAdapterName should be freed
+														* manually for every NERO_SCSI_DEVICE_INFO structures returned ! */
+							 
+
+/* NeroAPI>=6.0.0.0: Update the information about a drive. */
+NEROAPI_API NERO_DRIVE_ERROR NADLL_ATTR NeroUpdateDeviceInfo(NERO_SCSI_DEVICE_INFO *devInfo // the device info to update
+												, NERO_MEDIA_TYPE mediaType // the media type to update the speed infos with
+												, void *reserved); // Must be NULL
+
+/* Get a string describing the given bit field of supported media
+   Free with NeroFreeMem();
+*/
+NEROAPI_API char *NADLL_ATTR NeroGetTypeNameOfMedia(NERO_MEDIA_SET media,void *reserved);
+
+/*
+// Open and close a device:
+*/
+NEROAPI_API NERO_DEVICEHANDLE NADLL_ATTR NeroOpenDevice(const NERO_SCSI_DEVICE_INFO* pDevInfo);  /* NULL for errors */
+NEROAPI_API void NADLL_ATTR NeroCloseDevice(NERO_DEVICEHANDLE aDeviceHandle);
+
+/*
+// NeroAPI > 5.5.9.10
+// Get available write speeds depending on medium type, free with NeroFreeMem().
+// Returns NULL for error
+*/
+  
+typedef enum
+{
+   ACCESSTYPE_WRITE,
+   ACCESSTYPE_READ
+} NERO_ACCESSTYPE;
+
+NEROAPI_API NERO_SPEED_INFOS * NADLL_ATTR NeroGetAvailableSpeeds(NERO_DEVICEHANDLE aDeviceHandle,
+							       NERO_ACCESSTYPE accessType,
+							       NERO_MEDIA_TYPE mediaType,
+							       void *reserved);
+
+/*
+ * NeroAPI >= 6.3.1.20e
+ * Booktype settings
+ */
+typedef enum tag_BookTypeSettings
+{
+	BTS_PHYSICAL_DISC_TYPE	= 0,	// Set booktype to physical disc type. E.g. if a DVD+R is loaded the booktype is set to DVD+R.
+	BTS_DVD_ROM				= 1,	// Set booktype to DVD-ROM for all types of DVDs (DVD+R, DVD+RW, DVD+R9 DL, ...).
+	BTS_UNMODIFIED			= 2,	// Don't send any booktype change command to the drive. This is useful, if you have changed the settings on the drive and want to use this setting.
+	BTS_AUTOMATIC			= 3		// Let NeroAPI decide, which booktype to use. This may depend from the recorder, medium type and compilation type that is burned.
+} NERO_BOOK_TYPE_SETTINGS;
+
+/**
+ * NeroAPI >= 7.0.5.6 
+ * Spare area allocation for BD-R/RE
+ */
+typedef enum
+{
+	SAS_NO_ACTION	= 0,		// Do nothing per default
+	SAS_ALLOCATE	= 1,		// Allocate default spare area
+	SAS_NO_ALLOCATE = 2			// Do not allocate spare area
+}
+NERO_SPARE_AREA_SETTINGS;
+
+/*
+ * NeroAPI > 5.5.10.7
+ * Get and set special low level options of devices
+ */
+typedef enum
+{
+	/*
+	 * Change booktype in recorder driver to the booktype given in <*value> and
+	 * perform changing Booktype on drive so that the booktype of a DVD recordable
+	 * disc is changed for subsequent writes until next power cycle.
+	 * void* is a pointer to NERO_BOOK_TYPE_SETTINGS in Nero(Set|Get)DeviceOption.
+	 *
+	 * For setting the booktype to DVD-ROM, set parameter to BTS_DVD_ROM (before
+	 * and including NeroAPI 6.3.1.20e: TRUE), to set to physical disc type set
+	 * parameter to BTS_PHYSICAL_DISC_TYPE (before and including NeroAPI 6.3.1.20e:
+	 * FALSE) and to not change the booktype settings on the drive set the parameter
+	 * to BTS_UNMODIFIED. To take effect the flag NBF_NO_BOOKTYPE_CHANGE in NeroBurn
+	 * should be set.
+	 * In NeroGetDeviceOption, TRUE is returned if the booktype on the drive is set
+	 * to DVD-ROM, FALSE otherwise.
+	 */
+	NERO_DEVICEOPTION_BOOKTYPE_DVDROM = 0,
+
+	/*
+	 * Set the number of blocks after that to switch from layer 0
+	 * to layer 1 when writing on a double layer medium. 
+	 * Notes:
+	 * - the number of blocks must be a multiple of 16
+	 * - the layer 0 must be >= totalDataSize/2, because there can
+	 *   never be more data on layer 1 than on layer 0.
+	 *
+	 * In NeroSetDeviceOption value is a pointer to a DWORD variable.
+	 * In NeroGetDeviceOption a pointer to a DWORD is returned.
+	 */
+	NERO_DEVICEOPTION_LAYERSWITCH = 1,
+
+	/*
+	 * NeroAPI >= 6.0.0.24: 
+	 * Set the booktype of the next DVD recordable that is written to the value given
+	 * in <*value>. the behaviour is similar as for NERO_DEVICEOPTION_BOOKTYPE_DVDROM
+	 * but the change is only made in the recorder driver and not on the drive.
+	 * This option is useful, if you do packetwriting.  To take effect when using NeroBurn
+	 * the flag NBF_NO_BOOKTYPE_CHANGE should be set.
+	 * void* is a pointer to NERO_BOOK_TYPE_SETTINGS in Nero(Set|Get)DeviceOption.
+	 * In NeroGetDeviceOption, TRUE is returned if the booktype in the recorder driver
+	 * is set to DVD-ROM, FALSE otherwise.
+	 */
+	NERO_DEVICEOPTION_BOOKTYPE_DVDROM_NEXT_WRITE = 2,
+
+	/*
+	 * Set the number of blocks after that to switch from layer 0
+	 * to layer 1 when writing on a double layer medium. In difference to
+	 * NERO_DEVICEOPTION_LAYERSWITCH the layer break is written
+	 * immediately to the disc, while otherwise it is set during burning.
+	 * Notes:
+	 * - the number of blocks must be a multiple of 16
+	 * - the layer 0 must be >= totalDataSize/2, because there can
+	 *   never be more data on layer 1 than on layer 0.
+	 *
+	 * In NeroSetDeviceOption value is a pointer to a DWORD variable.
+	 * In NeroGetDeviceOption a pointer to a DWORD specifying any physically
+	 * set layer break point on the medium or NULL if no layer break point
+	 * has been set as of yet is returned
+	 */
+	NERO_DEVICEOPTION_BREAK_LAYER = 3,
+
+	/** 
+	 * NeroAPI >= 7.0.5.6 
+	 * Set/get spare area on BD. 
+	 * In NeroSetDeviceOption <*value> is a pointer to NERO_SPARE_AREA_SETTINGS
+	 * which will be allocated on the next burning.
+	 * In NeroGetDeviceOption <void*> is a pointer to DWORD specifying the number
+	 * of allocated spare area sectors. 
+	 */
+	NERO_DEVICEOPTION_SPARE_AREA = 4
+} 
+NERO_DEVICEOPTION;
+
+/*
+// Set a special option for a device
+// returns 0 an success
+*/
+NEROAPI_API int NADLL_ATTR NeroSetDeviceOption(NERO_DEVICEHANDLE aDeviceHandle,
+									NERO_DEVICEOPTION aOption,
+									void *value);
+
+/*
+// Get an option from a device. The returned value must be freed with NeroFreeMem
+// by the caller
+*/
+NEROAPI_API void* NADLL_ATTR NeroGetDeviceOption(NERO_DEVICEHANDLE aDeviceHandle,
+									NERO_DEVICEOPTION aOption, void* reserved);
+
+
+/*
+// CD-Information:
+*/
+
+typedef enum
+{
+	NTT_UNKNOWN,
+	NTT_DATA,
+	NTT_AUDIO
+} NERO_TRACK_TYPE;
+
+
+/* NeroAPI > 6.6.0.3
+ * Define the type of file system present in the particular track.
+ */
+typedef enum
+{
+	NTFST_UNKNOWN	= 0,
+	NTFST_ISO		= (1<<0),
+	NTFST_UDF		= (1<<1),		
+	NTFST_HFS		= (1<<2),
+	NTFST_FAT         = (1<<3),
+	NTFST_DATA        = (1<<4),
+	NTFST_AUDIO       = (1<<5),
+	NTFST_CDRFS       = (1<<6),
+	NTFST_DIRECTCD    = (1<<7),
+	NTFST_PACKETCD    = (1<<8),
+	NTFST_JOLIET      = (1<<9),
+	NTFST_BOOTABLE    = (1<<10),
+	NTFST_DATA_MODE_1 = (1<<11),
+	NTFST_DATA_MODE_2 = (1<<12),
+}
+NERO_TRACK_FS_TYPE;
+
+typedef struct tag_NERO_TRACK_INFO
+{
+	DWORD			ntiSessionNumber;
+	DWORD			ntiTrackNumber;
+	NERO_TRACK_TYPE	ntiTrackType;
+	DWORD			ntiTrackStartBlk;
+	DWORD			ntiTrackLengthInBlks;
+	char			ntiArtist[65];
+	char			ntiTitle[65];
+	char			ntiISRC[13];			/* NeroAPI > 5.5.8.3: if NGCDI_READ_ISRC is present: 12 chars ISRC code + terminator */
+	DWORD			ntiBlockSize;           /* NeroAPI >= 6.0.0.0: size of one block in bytes */
+	DWORD			ntiFSType;				/* NeroAPI > 6.6.0.3 type of tracks file system. Can be combination of multiple file systems. */			
+	DWORD			ntiReserved[27];        /* Should be zero */
+} NERO_TRACK_INFO;
+
+typedef enum
+{
+	NMT_UNKNOWN,
+	NMT_CD_ROM,
+	NMT_CD_RECORDABLE,
+	NMT_CD_REWRITEABLE
+} NERO_MEDIUM_TYPE;
+
+/** Book types the inserted disc have. In seldom cases, beside DVD-ROM, it may differ from the
+ * physical disc type. */
+typedef enum 
+{
+	NBT_UNKNOWN,		// Unknown
+	NBT_DVD_ROM,		// DVD-ROM	
+	NBT_DVD_RAM,		// DVD-RAM	
+	NBT_DVD_M_R,		// DVD-R	
+	NBT_DVD_P_R,		// DVD+R
+	NBT_DVD_M_RW,		// DVD-RW
+	NBT_DVD_P_RW,		// DVD+RW
+	NBT_DVD_P_R_DL,		// DVD+R Dual Layer
+} 
+NERO_BOOK_TYPE;
+
+
+typedef struct tag_NERO_CD_INFO
+{
+	DWORD            ncdiFreeCapacityInBlocks;
+	BOOL             ncdiIsWriteable;       /* A disc can be non-writeable */
+	NERO_MEDIUM_TYPE ncdiMediumType;        /* Old media type description, ncdiMediaType should be used instead */
+	char             ncdiArtist[65];
+	char             ncdiTitle[65];
+	DWORD			 ncdiAvailableEraseModes;/* This bitfield can be decoded using the NCDI_IS_ERASE_MODE_AVAILABLE macro */
+	DWORD			 ncdiUnusedBlocks;		/* difference beetween Lead-Out position and last possible Lead-Out position */
+	NERO_MEDIA_TYPE	 ncdiMediaType;			/* NeroAPI>=5.5.9.4: type of media */
+	DWORD			 ncdiMediumFlags;		/* NeroAPI>6.0.0.10: various medium flags (Virtual multisession, ...)  */
+/* The medium is a virtual multisession medium, use VMS API to retrieve session information.
+   NOTE: This flag only tells you, that if multisession is written, VMS is used. But not
+         that this medium contains multisessions.
+*/
+#define NCDIMF_VIRTUALMULTISESSION	(1<<0)
+#define NCDIMF_HDB_SUPPORTED		(1<<1)  /* The medium supports HD-BURN */
+#define NCDIMF_FINALIZED_DISC		(1<<2)  /* NeroAPI >= 6.6.0.12: Disc is finalized. No further writing possible */
+
+	DWORD            ncdiLayer0MaxBlocks;   /* NeroAPI>6.0.0.19: If this value is set, the medium is a double layer medium whereby 
+	                                         * layer 0 can not be bigger than the given number of blocks.
+                                             */
+	DWORD            ncdiTotalCapacity;		/* NeroAPI>=6.3.0.5: The total capacity of this medium */
+	NERO_BOOK_TYPE	 ncdiBookType;			/* NeroAPI>=6.6.0.11: Book type of current disc or NBT_UNKNOWN, if could not be read. */
+	DWORD            ncdiReserved[25];      /* Should be zero */
+	DWORD            ncdiNumTracks;
+	NERO_TRACK_INFO  ncdiTrackInfos[1];
+} NERO_CD_INFO;
+
+#define NCDI_IS_ERASE_MODE_AVAILABLE(cdInfo,eraseMode)	((cdInfo).ncdiAvailableEraseModes & (1<<(eraseMode)))
+
+
+
+// NeroAPI >= 6.6.1.0
+// Get the actual medium type inside the recorder.
+// Returns MEDIA_NONE if no media is inside.
+//
+NEROAPI_API NERO_MEDIA_TYPE NADLL_ATTR NeroGetCurrentMediumType(NERO_DEVICEHANDLE aDeviceHandle);
+
+
+/*
+// Get information about a CD. Free result with NeroFreeMem().
+//
+// aDeviceHandle: result of NeroOpenDevice()
+//         flags: see below
+//
+// Returns NULL in case of error.
+*/
+NEROAPI_API NERO_CD_INFO * NADLL_ATTR NeroGetCDInfo(NERO_DEVICEHANDLE aDeviceHandle, DWORD dwFlags);
+#define NGCDI_READ_CD_TEXT      (1<<0)		/* also try to fill in */
+#define NGCDI_READ_ISRC			(1<<1)		/* NeroAPI>=5.5.8.4 */
+/* NeroAPI>=6.0.0.25: 
+ * If the recorder and the current medium support HD-BURN, give the capacity and 
+ * the unused blocks for the HD-BURN mode 
+ * Note, that if the medium is already written in HD-BURN mode, this flag is not necessary.
+ */
+#define NGCDI_USE_HDB			(1<<2)
+/* NeroAPI > 6.6.0.3
+ * Get extended disc info, e.g. file system type of particular track.
+ * This can take a little bit more time, therefore set it only if such
+ * information is really required.  */
+#define NGCDI_EXTENDED			(1<<3)
+	
+
+typedef struct tag_NERO_VMSSESSION
+{
+	char		nvmssSessionName[256];		/* The name of the session (volume name) */
+	struct tm	nvmssCreationTime;			/* The creation time of the session */
+	DWORD		nvmssNextWritableAddress;	/* The first block that is not occupied by this session */
+	DWORD		nvmssReserved[32];			/* Should be zero */
+} NERO_VMSSESSION;
+
+typedef struct tag_NERO_VMS_INFO
+{
+	DWORD			nvmsiNextWritableAddress;	/* The next writable address of the medium, may be used for free space calculation */
+	DWORD			nvmsiNumSessions;			/* Number of sessions stored on the VMS medium */
+	DWORD			nvmsiReserved[32];			/* Should be zero */
+	NERO_VMSSESSION	nvmsiSessionInfo[1];		/* One entry per session */
+} NERO_VMS_INFO;
+
+
+/*
+// NeroAPI>6.0.0.10: Retrieve virtual multisession information for media supporting it.
+// This function may be called for media having the NCDIMF_VIRTUALMULTISESSION flag
+// set in their NERO_CD_INFO structure. Free result with NeroFreeMem()
+//
+// aDeviceHandle: result of NeroOpenDevice()
+//         flags: currently unused, reserved for future extensions
+//
+// Returns NULL in case of error (e.g. non-VMS medium inserted)
+//
+// Virtual multisession is a technique to allow writing multisession discs on
+// medium types that does not support normal multisession, e.g. DVD-+RW.
+*/
+NEROAPI_API NERO_VMS_INFO * NADLL_ATTR NeroGetVMSInfo(NERO_DEVICEHANDLE aDeviceHandle, DWORD dwFlags);
+
+
+/*
+// NeroAPI>=5.5.9.16: Get information about a disc image. Result must be released using NeroFreeMem().
+//
+// imagePath: path to the image file
+// reserved: reserved for future usage
+// 
+// Returns NULL in case of error.
+*/
+NEROAPI_API NERO_CD_INFO * NADLL_ATTR NeroGetDiscImageInfo(const char *imagePath, void *reserved);
+
+/*
+// A progress display could look like this:
+//
+// +------------------------------------------------------+
+// | Log of Operation:                                    |
+// | +--------------------------------------------------+ |
+// | | [icon] text                                      | |
+// | | ...........                                      | |
+// | |                                                  | |
+// | +--------------------------------------------------+ |
+// | Current Phase: text                                  |
+// |      Progress: ********............................  |
+// |                                                      |
+// |                       ABORT                          |
+// +------------------------------------------------------+
+//
+// The application may provide callback functions to set
+// the different parts of this display. All of them may
+// be NULL.
+*/
+typedef BOOL  (NERO_CALLBACK_ATTR *NERO_PROGRESS_CALLBACK)(void *pUserData, DWORD dwProgressInPercent); /* Will return TRUE if the user wants to abort */
+typedef BOOL  (NERO_CALLBACK_ATTR *NERO_ABORTED_CALLBACK)(void *pUserData);                             /*  "     "     "    "  "    "    "    "   "   */
+typedef enum
+{
+	NERO_TEXT_INFO,        /* informative text                     */
+	NERO_TEXT_STOP,        /* some operation stopped prematurely   */
+	NERO_TEXT_EXCLAMATION, /* important information                */
+	NERO_TEXT_QUESTION,    /* a question which requires an answer  */
+	NERO_TEXT_DRIVE,       /* a message concerning a CD-ROM drive or recorder */
+	NERO_TEXT_FILE,        /* a message concerning a file          */
+	NERO_TEXT_UNSPECIFIED  /* no type specified                    */
+} NERO_TEXT_TYPE;       
+
+typedef enum
+{
+	NERO_PHASE_UNSPECIFIED					=-1,
+	NERO_PHASE_START_CACHE					=24,
+	NERO_PHASE_DONE_CACHE					=25,
+	NERO_PHASE_FAIL_CACHE					= 26,
+	NERO_PHASE_ABORT_CACHE					= 27,
+	NERO_PHASE_START_TEST					=28,
+	NERO_PHASE_DONE_TEST					=29,
+	NERO_PHASE_FAIL_TEST					= 30,
+	NERO_PHASE_ABORT_TEST					= 31,
+	NERO_PHASE_START_SIMULATE				=32,
+	NERO_PHASE_DONE_SIMULATE				=33,
+	NERO_PHASE_FAIL_SIMULATE				= 34,
+	NERO_PHASE_ABORT_SIMULATE				= 35,
+	NERO_PHASE_START_WRITE					=36,
+	NERO_PHASE_DONE_WRITE					=37,
+	NERO_PHASE_FAIL_WRITE					= 38,
+	NERO_PHASE_ABORT_WRITE					= 39,
+	NERO_PHASE_START_SIMULATE_NOSPD			=61,
+	NERO_PHASE_DONE_SIMULATE_NOSPD			=62,
+	NERO_PHASE_FAIL_SIMULATE_NOSPD			= 63,
+	NERO_PHASE_ABORT_SIMULATE_NOSPD			= 64,
+	NERO_PHASE_START_WRITE_NOSPD			=65,
+	NERO_PHASE_DONE_WRITE_NOSPD				=66,
+	NERO_PHASE_FAIL_WRITE_NOSPD				= 67,
+	NERO_PHASE_ABORT_WRITE_NOSPD			= 68,
+	NERO_PHASE_PREPARE_ITEMS				= 73,
+	NERO_PHASE_VERIFY_COMPILATION			= 78,
+	NERO_PHASE_VERIFY_ABORTED				= 79,
+	NERO_PHASE_VERIFY_END_OK				= 80,
+	NERO_PHASE_VERIFY_END_FAIL				= 81,
+	NERO_PHASE_ENCODE_VIDEO					=82,
+	NERO_PHASE_SEAMLESSLINK_ACTIVATED      = 87,  // deprecated, use NERO_PHASE_BUP_ACTIVATED below
+	NERO_PHASE_BUP_ACTIVATED				=90,  // Generic: Buffer underun protection activated
+	NERO_PHASE_START_FORMATTING				= 98, 
+	NERO_PHASE_CONTINUE_FORMATTING			=99,
+	NERO_PHASE_FORMATTING_SUCCESSFUL		=100,
+	NERO_PHASE_FORMATTING_FAILED            =101,
+	NERO_PHASE_PREPARE_CD					=105,
+	NERO_PHASE_DONE_PREPARE_CD				=106,
+	NERO_PHASE_FAIL_PREPARE_CD				=107,
+	NERO_PHASE_ABORT_PREPARE_CD				=108,
+	NERO_PHASE_DVDVIDEO_DETECTED			=111,
+	NERO_PHASE_DVDVIDEO_REALLOC_STARTED		=112,
+	NERO_PHASE_DVDVIDEO_REALLOC_COMPLETED	=113,
+	NERO_PHASE_DVDVIDEO_REALLOC_NOTNEEDED	=114, // NeroAPI > 5.5.9.3
+	NERO_PHASE_DVDVIDEO_REALLOC_FAILED		=115,  // NeroAPI > 5.5.9.3
+	NERO_PHASE_DRM_CHECK_FAILURE			=169,  // NeroAPI >= 6.3.0.6
+	/** Start Burn-at-once phases **/
+	NERO_PHASE_START_WRITE_DATAFILES		=171,	// Writing data files started
+	NERO_PHASE_DONE_WRITE_DATAFILES			=172,   // Writing data files completed successfully
+	NERO_PHASE_FAIL_WRITE_DATAFILES			=173,	// Writing data files failed
+	NERO_PHASE_WARN_WRITE_DATAFILES			=174,	// Writing data files completed with warnings
+	NERO_PHASE_START_BAO_FINALIZE			=175,	// Finalizing disc started
+	NERO_PHASE_FAIL_BAO_FINALIZE			=176,	// Finalizing the disc failed
+	NERO_PHASE_DONE_BAO_FINALIZE			=177,	// Disc finalized successfully
+	NERO_PHASE_FAIL_BAO_PREPARE				=178,	// Preparing the disc failed
+	NERO_PHASE_FAIL_BAO_WRITEFILE			=179,	// Writing file to disc failed
+	/** End Burn-at-once phases **/
+	NERO_PHASE_BURN_LAYER_1					=180,	// Starting writing on layer 1 of a double layer disc
+	NERO_PHASE_BURN_LAYER_2					=181,	// Starting writing on layer 2 of a double layer disc
+} NERO_MAJOR_PHASE;
+
+/* a one-line text to be displayed; text pointer becomes invalid after returning from this function */
+typedef void  (NERO_CALLBACK_ATTR *NERO_ADD_LOG_LINE_CALLBACK)(void *pUserData, NERO_TEXT_TYPE type, const char *text); 
+
+/* set the phase line; text pointer becomes invalid after returning from this function */
+typedef void  (NERO_CALLBACK_ATTR *NERO_SET_PHASE_CALLBACK)(void *pUserData, const char *text);                         
+
+/* Tell the main program whether the burn process can be interrupted or not */
+typedef void (NERO_CALLBACK_ATTR *NERO_DISABLE_ABORT_CALLBACK)(void *pUserData,BOOL abortEnabled);
+
+/* Let the application knows in which part of the burn process NeroAPI is */
+typedef void (NERO_CALLBACK_ATTR *NERO_SET_MAJOR_PHASE_CALLBACK)(void *pUserData,NERO_MAJOR_PHASE phase,void *reserved);
+
+typedef struct tag_NERO_PROGRESS
+{
+	NERO_PROGRESS_CALLBACK npProgressCallback;
+	NERO_ABORTED_CALLBACK npAbortedCallback;
+	NERO_ADD_LOG_LINE_CALLBACK npAddLogLineCallback;
+	NERO_SET_PHASE_CALLBACK npSetPhaseCallback;
+	void *npUserData;
+	NERO_DISABLE_ABORT_CALLBACK npDisableAbortCallback;		/* Will be called only if the NBF_DISABLE_ABORT flags is given to the NeroBurn function */
+	NERO_SET_MAJOR_PHASE_CALLBACK npSetMajorPhaseCallback;	
+	NERO_PROGRESS_CALLBACK npSubTaskProgressCallback;		/* provide the write buffer fill level */
+} NERO_PROGRESS;
+
+/*
+// NeroAPI >= 6.0.0.0
+// creates a NERO_PROGRESS structure correctly initialised.
+// Must be freed with NeroFreeMem when no longer needed.
+*/
+NEROAPI_API NERO_PROGRESS* NADLL_ATTR NeroCreateProgress();
+
+/*
+// Data exchange between application and NeroAPI is done with
+// a function that gets a pointer to its own structure, a buffer
+// pointer and the amount in bytes to be read or written. It
+// shall return the actual amount of bytes transferred. Other
+// functions indicate that the EOF file has been reached when
+// reading or a serious error occured.
+*/
+typedef DWORD (NERO_CALLBACK_ATTR *NERO_IO_CALLBACK)(void *pUserData, BYTE *pBuffer, DWORD dwLen);
+typedef BOOL (NERO_CALLBACK_ATTR *NERO_STATUS_CALLBACK)(void *pUserData);
+typedef struct tag_NERO_IO
+{
+	void                 *nioUserData;
+	NERO_IO_CALLBACK     nioIOCallback;
+	NERO_STATUS_CALLBACK nioEOFCallback;          // shall return TRUE if further IO calls will always fail to transfer any data, i.e. EOF reached
+	NERO_STATUS_CALLBACK nioErrorCallback;        // shall return TRUE if an error occured during an IO call
+} NERO_IO;
+
+
+/* A pointer on this structure will be passed with the DLG_WAITCD_MEDIA_INFO user dialog callback 
+   (NeroAPI>=5.5.9.4)
+*/
+
+typedef struct 
+{
+	DWORD ndwmiSize;
+	NERO_MEDIA_TYPE ndwmiLastDetectedMedia;
+	NERO_MEDIA_SET	ndwmiRequestedMedia;
+	const char *ndwmiLastDetectedMediaName;
+	const char *ndwmiRequestedMediaName;
+} NERO_DLG_WAITCD_MEDIA_INFO;
+
+
+
+/*
+// ISO track generation functions
+*/
+
+typedef struct tag_NERO_ISO_ITEM
+{
+	char fileName[252];						// Deprecated, use longFileName instead
+	char *longFileName;				// File name on the burnt CD 
+									// (will be freed in NeroFreeIsoItem if this item is a reference)
+
+	BOOL isDirectory;						// Is this item a directory ?
+	BOOL isReference;						// Is this item a reference to a file/directory of a previous session
+    // when recording RockRidge, you can set the name of a directory to be used for
+	// retrieving rockridge informations here
+	char sourceFilePath[252];				// Deprecated, use longSourceFilePath instead
+	const char *longSourceFilePath;			// Path to the file, including file name (ignored for a directory)
+	struct tag_NERO_ISO_ITEM *subDirFirstItem;	// Point on the first item of the sub directory if the item is a directory 
+											// Can be NULL if the directory is empty
+											// (ignored for a file)
+	struct tag_NERO_ISO_ITEM *nextItem;			// Next item in the current directory
+	void *userData;							// Can be used to store additional informations
+
+	// Used to reference a file from a previous session
+	long dataStartSec;
+	__int64 dataLength;
+	struct tm entryTime;
+    int itemSize;  							// Size of the structure
+    struct CImportInfo *importinfo;			// ImportInfo
+
+    WCHAR *unicodeFileName;					// NeroAPI>=6.6.0.0: file name on the burnt CD in unicode format. If unicodeFileName is present,	it supersedes fileName and longFileName.
+											// (will be freed in NeroFreeIsoItem if this item is a reference)
+} NERO_ISO_ITEM;
+
+typedef struct tag_NERO_IMPORT_DATA_TRACK_INFO
+{
+	DWORD nidtiSize;			// Must contain the size of the structure
+	char *nidtipVolumeName;		// This must be released using NeroFreeMem
+} NERO_IMPORT_DATA_TRACK_INFO;
+
+// NeroCreateIsoItem: Allocate an instance from the NERO_ISO_ITEM structure
+//    The itemSize member of the structure will be automatically be filled by this
+//    function
+#define NeroCreateIsoItem()	NeroCreateIsoItemOfSize(sizeof(NERO_ISO_ITEM))
+NEROAPI_API NERO_ISO_ITEM * NADLL_ATTR NeroCreateIsoItemOfSize(size_t);
+
+// Free an instance from the NERO_ISO_ITEM structure
+// longFilename is only freed if this item is a reference, because only then is longFilename allocated by NeroAPI
+NEROAPI_API void NADLL_ATTR NeroFreeIsoItem(NERO_ISO_ITEM *);
+
+/*
+// NeroAPI >= 6.0.0.0:
+// Free an NERO_ISO_ITEM including all linked items
+*/ 
+NEROAPI_API void NADLL_ATTR NeroFreeIsoItemTree(NERO_ISO_ITEM*);
+   
+// NeroCopyIsoItem: Create a copy of an existing NERO_ISO_ITEM object.
+//    This is a safe way to obtain an exact copy of NERO_ISO_ITEM objects imported
+//    from a previous session
+//    Note that the new NERO_ISO_ITEM's nextItem,userData and subDirFirstItem members are set to NULL
+//    longFilename is only copied if this item is a reference, because only then is longFilename allocated by NeroAPI
+//    Available for NeroAPI versions >5.5.9.9
+NEROAPI_API NERO_ISO_ITEM * NADLL_ATTR NeroCopyIsoItem(const NERO_ISO_ITEM *iso_item);
+
+// Create an ISO track from a NERO_ISO_ITEM tree
+// NeroAPI >= 5.5.9.0:
+// For special needs you have to give a pointer to NeroCITEArgs instead of name.
+// See declaration of NeroCiteArgs below. Set flags to NCITEF_USE_STRUCT,
+// to tell NeroCreateIsoTrackEx that name is a NeroCITEArgs struct and set the flags
+// for the burn options with NeroCITEArgs::dwBurnOptions. root should also be NULL
+// in this case.
+NEROAPI_API
+struct CNeroIsoTrack * NADLL_ATTR NeroCreateIsoTrackEx(NERO_ISO_ITEM *root,	// First item of the root directory
+						       const char *name,				// Name of the CD
+						       DWORD flags);					// See constants below
+
+// NeroAPI >= 6.6.0.13
+// Ability to set desired UDF revision and partition type of created UDF file system.
+// These methods will have no effect, if the track does not contain UDF part.
+typedef enum
+{
+  NUR_UDF_INVALID,
+  NUR_UDF_102,
+  NUR_UDF_150,
+  NUR_UDF_200,
+  NUR_UDF_201,
+  NUR_UDF_250
+
+} NERO_UDF_REVISION;
+
+NEROAPI_API BOOL NADLL_ATTR NeroSetDesiredUDFRevision(struct CNeroIsoTrack *track,
+						      NERO_UDF_REVISION desiredRevision);
+
+typedef enum
+{
+  NUPT_INVALID,
+  NUPT_PHYSICAL,
+  NUPT_VIRTUAL,
+  NUPT_SPARING
+
+} NERO_UDF_PARTITION_TYPE;
+
+NEROAPI_API BOOL NADLL_ATTR NeroSetDesiredUDFPartitionType(struct CNeroIsoTrack *track,
+							   NERO_UDF_PARTITION_TYPE desiredPartitionType);
+
+
+// this struct can be used to give some more parameters to NeroCreateIsoTrackEx:
+// - If a CD shall have two different filesystems (e.g. HFS+ CDs), you can give
+// the second filesystem with firstRootItem_wrapper.
+// - give some information to be written to the volume descriptor
+typedef struct tag_NERO_CITE_ARGS {
+	int size; // ignored. Initialise whole struct with 0. The version of the
+	          // struct will be taken from expected version of NeroAPI
+	NERO_ISO_ITEM *firstRootItem;
+	NERO_ISO_ITEM *firstRootItem_wrapper;
+	const char    *name;
+	DWORD          dwBurnOptions;
+	// NeroAPI >= 5.5.9.26: 
+	const char    *systemIdentifier; // system identifier
+	const char    *volumeSet;
+	const char    *publisher; // the publisher of this track
+	const char    *dataPreparer; // the preparer of this track
+	const char    *application; // the application, that created this track
+	const char    *copyright; // copyright file
+	const char    *abstract;  // abstract file
+	const char    *bibliographic; // bibliographic file
+} NERO_CITE_ARGS;
+
+// definition for compatibility reasons
+#define NeroCITEArgs NERO_CITE_ARGS
+
+#define NCITEF_USE_JOLIET		(1<<0)
+#define NCITEF_USE_MODE2		(1<<1)
+#define NCITEF_USE_ROCKRIDGE	(1<<2)
+#define NCITEF_CREATE_ISO_FS	(1<<3)
+#define NCITEF_CREATE_UDF_FS	(1<<4)
+#define NCITEF_CREATE_HFS_FS    (1<<5)
+#define NCITEF_DVDVIDEO_REALLOC	(1<<6)	// NeroAPI>=5.5.7.8:  Perform reallocation of files in the VIDEO_TS directory; NeroAPI>=6.3.1.4: Also create layerbreak if writing on a double layer medium
+#define NCITEF_USE_STRUCT	    (1<<7)	// NeroAPI>=5.5.9.0:  'name' points to an argument struct instead of name. If set, 'root' and other 'flags' are ignored.
+#define NCITEF_RESERVED1        (1<<8)  // Reserved
+#define NCITEF_USE_ALLSPACE	    (1<<9)	// NeroAPI>=5.5.9.17: Use all space available on the medium for the volume to be created. Supported for DVD+-RW only
+#define NCITEF_RESERVED2	    (1<<10)	// Reserved
+#define NCITEF_RESERVED3        (1<<11) // Reserved
+#define NCITEF_RESERVED4		(1<<12) // Reserved
+#define NCITEF_RELAX_JOLIET		(1<<13)	// NeroAPI>=6.0.0.0:Relax joliet filename length limitations -> allow a maximum of 109 characters per filename
+#define NCITEF_DVDVIDEO_CMPT	(1<<14)	// NeroAPI>6.0.0.13:  Create DVD-Video compatible medium, NCITEF_CREATE_ISO_FS and NCITEF_CREATE_UDF_FS must be set,
+                                        //                    NCITEF_DVDVIDEO_REALLOC may be set to reallocate DVD-Video .IFO pointers
+										//					  Note that NeroAPI versions prior or equal to 6.0.0.13 will implicitly enable DVD-Video compatibility
+										//					  when DVD-Video content is found within your compilation
+#define NCITEF_RESERVED5		(1<<15)	// Reserved
+#define NCITEF_RESERVED6		(1<<16)	// Reserved
+#define NCITEF_RESERVED7		(1<<17) // Reserved
+
+// Free an ISO track previously allocated with NeroCreateIsoTrackEx
+
+NEROAPI_API void NADLL_ATTR NeroFreeIsoTrack(struct CNeroIsoTrack *track);
+
+typedef enum 
+{
+	NIDTR_NO_ERROR=0,
+	NIDTR_GENERIC_ERROR, // undefined error
+	NIDTR_DRIVE_ERROR, // get more details with NeroGetLastDriveError
+	// filesystem errors below, maybe a corrupted filesystem etc.
+	// If one of these is returned, parts of the filesystem may have
+	// been imported nevertheless
+	NIDTR_READ_ERROR, // error while reading from the disc
+	NIDTR_INVALID_FS, // errors in the filesystem on the disc	
+	NIDTR_INVALID_TRACKNUMBER // the tracknumber given is invalid
+} NERO_IMPORT_DATA_TRACK_RESULT;
+
+/*
+// Create a NERO_ISO_ITEM tree from an already existing ISO track in order to create a new session
+// with reference to files from older sessions
+// *ppCDStamp will be filled with a pointer on a CDStamp object which will have to be freed later
+// *pInfo will be filled with information about the imported track
+// *result will contain a result flag, may be NULL
+// (NeroAPI>=6.0.0.0)
+*/
+NEROAPI_API NERO_ISO_ITEM *NADLL_ATTR NeroImportDataTrack(	NERO_DEVICEHANDLE pRecorder,
+												DWORD trackNumber,
+												void **ppCDStamp,
+												NERO_IMPORT_DATA_TRACK_INFO *pInfo,
+												DWORD flags,
+												NERO_IMPORT_DATA_TRACK_RESULT *result,
+												void *reserved);		// Must be NULL
+#define NIITEF_IMPORT_ROCKRIDGE		(1<<0) // Will be ignored, RockRidge is now always imported if present
+#define NIITEF_IMPORT_ISO_ONLY		(1<<1)
+#define NIITEF_PREFER_ROCKRIDGE		(1<<2) // Will be ignored
+#define NIITEF_IMPORT_UDF			(1<<3) // Import UDF Session
+#define NIITEF_IMPORT_VMS_SESSION	(1<<4) // treat trackNumber as the virtual multisession session specifier
+
+// Free a CD stamp allocated by NeroImportIsoTrackEx
+
+NEROAPI_API void NADLL_ATTR NeroFreeCDStamp(void *pCDStamp);
+
+// Create a file system container for the NERO_FILE_SYSTEM_CONTAINER_MEDIA compilation type
+
+#ifdef __cplusplus
+namespace FileSystemContent
+{
+	struct IFileSystemDescContainer;
+};
+#else //__cplusplus
+struct IFileSystemDescContainer;
+#endif//__cplusplus
+
+NEROAPI_API 
+#ifdef __cplusplus
+FileSystemContent::
+#else //__cplusplus
+struct
+#endif//__cplusplus
+IFileSystemDescContainer *NADLL_ATTR NeroCreateFileSystemContainer(void *reserved);
+
+
+/*
+// Recording functions:
+*/
+
+typedef enum
+{
+	NERO_ET_FILE,			/* read/write to/from WAV file. */
+	NERO_ET_IO_CALLBACK,	/* exchange data with application directly */
+	NERO_ET_FILE_MP3,		/* read from MP3 file (not for DAE) */
+	NERO_ET_FILE_WMA,		/* read from MS audio file (not for DAE) */
+    NERO_ET_FILE_RAW,        /* for a Freestyle compilation,
+					 * this and NERO_ET_IO_CALLBACK
+					 * are the only types allowed
+					 * at the moment.
+					 * It will expect files 
+					 * to be in the format
+					 * as to be written to the disc.
+					 * This exchange type is valid
+					 * for freestyle compilations only */
+
+	NERO_ET_AUDIO_FILE	/* NeroAPI > 5.5.9.8: audio file created with the plugin manager*/
+
+} NERO_DATA_EXCHANGE_TYPE;
+
+typedef void * NERO_AUDIO_ITEM_HANDLE;
+
+typedef struct tagNERO_AUDIO_ITEM_INFO
+{
+	NERO_AUDIO_ITEM_HANDLE	naiiAudioItem;
+	const char				*naiiFileName;
+} NERO_AUDIO_ITEM_INFO;
+
+/* use PCM, 44.1kHz, Stereo (left channel first), 16 bits per channel, LSB,
+   when exchanging data with the NeroAPI */
+typedef	struct tag_NERO_DATA_EXCHANGE
+{
+	NERO_DATA_EXCHANGE_TYPE ndeType;
+	union
+	{
+		char			ndeFileName[256];      // Deprecated, use ndeLongFileName.ptr instead
+		struct
+		{
+			DWORD	reserved;				   /* must be 0	*/
+			const char 	*ptr;				   
+		} ndeLongFileName;
+		NERO_IO			ndeIO;                 // NERO_IO/EOF/ERROR_CALLBACK
+
+		NERO_AUDIO_ITEM_INFO	ndeAudioItemInfo; // NeroAPI > 5.5.9.8
+	} ndeData;
+} NERO_DATA_EXCHANGE;
+		
+typedef struct tag_NERO_AUDIO_TRACK
+{
+	DWORD natPauseInBlksBeforeThisTrack;
+	DWORD natNumIndexPositions;
+	/* NOTE: values of index positions has to be given in bytes,
+	 * whereby the values have to be a multiple of 2352
+	 */
+	DWORD natRelativeIndexBlkPositions[98];  /* offsets between one index position and the next one */
+	const char *natTitle, *natArtist;        /* set to NULL if unknown or to be taken from source */
+	NERO_DATA_EXCHANGE natSourceDataExchg;
+	DWORD natLengthInBlocks;                 /* only used for NERO_IO_CALLBACK */
+	BOOL  natIndex0ContainsData;			 /* NeroAPI 5.5.9.8: TRUE, if audio data shall be written into index 
+												0. Data for index 0 must be provided. */
+	DWORD natReserved[31];                   /* Should be zero */
+} NERO_AUDIO_TRACK;
+
+typedef enum
+{
+   NERO_TRACKMODE_MODE1,         /* 2048 Bytes per sector data track */
+   NERO_TRACKMODE_MODE2_FORM1,   /* 2048 Bytes per sector, used for multisession */
+   NERO_TRACKMODE_AUDIO          /* 2352 Bytes per sector, standard audio track */
+} NERO_TRACKMODE_TYPE;
+   
+typedef struct tag_NERO_FREESTYLE_TRACK
+{
+    DWORD nftStructureSize;                     /* size of this structure, to ensure binary compatibility */
+	DWORD nftPauseInBlksBeforeThisTrack;
+	DWORD nftNumIndexPositions;
+	DWORD nftRelativeIndexBlkPositions[98];  /* offsets between one index position and the next one */
+	const char *nftTitle, *nftArtist;        /* set to NULL if unknown or to be taken from source */
+	NERO_DATA_EXCHANGE nftSourceDataExchg;   /* source for raw track data */
+	DWORD nftLengthInBlocks;                 /* only used for NERO_IO_CALLBACK */
+    NERO_TRACKMODE_TYPE nftTracktype;           /* specifies track type to be written */
+} NERO_FREESTYLE_TRACK;
+      
+typedef enum
+{
+	NERO_MPEG_ITEM,
+	NERO_JPEG_ITEM,
+	NERO_NONENCODED_VIDEO_ITEM,	// The source file name will be an AVI file which will be encoded into MPG by NeroAPI
+} NERO_VIDEO_ITEM_TYPE;
+
+typedef struct tag_NERO_VIDEO_ITEM
+{
+	DWORD nviPauseAfterItem;			// value is number of blocks (75 blocks = 1 second)
+	char nviSourceFileName[250];		// Deprecated, use nviLongSourceFileName instead
+	const char *nviLongSourceFileName;	// MPG, JPG or AVI file
+	NERO_VIDEO_ITEM_TYPE nviItemType;
+} NERO_VIDEO_ITEM;
+
+typedef enum
+{
+	NERO_ISO_AUDIO_MEDIA			=0,	// Burn either a CD or a DVD, depending on the nwcdMediaType member
+	NERO_VIDEO_CD					=1,
+	NERO_BURN_IMAGE_MEDIA			=2,	// Burn either a CD or a DVD from an image
+    NERO_FREESTYLE_CD				=3,
+	NERO_FILE_SYSTEM_CONTAINER_MEDIA=4,	// Burn an IFileSystemDescContainer (see NeroFileSystemContainer.h) 
+
+	// For compatibility
+	NERO_ISO_AUDIO_CD				=0,
+	NERO_BURN_IMAGE_CD				=2
+} NERO_CD_FORMAT;
+
+typedef struct tag_NERO_WRITE_CD
+{
+	/* both may be NULL: */
+	const char *nwcdArtist;
+	const char *nwcdTitle;
+
+	struct CNeroIsoTrack *nwcdIsoTrack;      /* if not NULL, then the disc will have an ISO track - please refer to "NeroIsoTrack.h" */
+	BOOL nwcdCDExtra;                        /* if TRUE and nwcdIsoTrack not NULL, then the resulting CD will have audio in the first session
+											    and the data track in the second, however, currently the NeroAPI does not add any of the
+												special CD Extra files to the data track. Of course there should be at least 1 audio track,
+												else this flag will be ignored. */
+	void *nwcdpCDStamp;						// Point on a CDStamp object if a particular CD is requested, otherwise NULL
+	DWORD nwcdNumTracks;
+
+	NERO_MEDIA_TYPE	nwcdMediaType;			/* Media on which the data should be written */
+	DWORD nwcdReserved[32];					/* Should be zero */
+
+	NERO_AUDIO_TRACK nwcdTracks[1];
+} NERO_WRITE_CD;
+
+#ifdef __cplusplus
+namespace VCDEngine
+{
+	struct IVCDFSContentGenerator;
+	struct IVCDMediaDescription;
+};
+#endif
+
+
+typedef enum
+{
+	NERO_VIDEO_RESOLUTION_PAL = 0,
+	NERO_VIDEO_RESOLUTION_NTSC = 1
+} NERO_VIDEO_RESOLUTION;
+
+
+typedef struct tag_NERO_WRITE_VIDEO_CD
+{
+	BOOL nwvcdSVCD;							// If TRUE, write a SVCD
+	DWORD nwvcdNumItems;
+	struct CNeroIsoTrack *nwvcdIsoTrack;
+	char nwvcdTempPath[252];				/* Deprecated, use nwvcdLongTempPath instead */
+	const char *nwvcdLongTempPath;			/* NeroAPI>=5.5.5.3: where the encoded files will be temporary stored */
+#ifdef __cplusplus							/* NeroAPI>=5.5.7.6 */
+	VCDEngine::IVCDFSContentGenerator *(*nwvcdCustomVCDEngine)(VCDEngine::IVCDMediaDescription *desc,FileSystemContent::IFileSystemDescContainer *pFSDC);
+#else
+	void *nwvcdCustomVCDEngine;
+#endif
+	NERO_VIDEO_RESOLUTION nwvcdEncodingResolution; /* NeroAPI >= 6.0.0.17: select the encoding resolution for the video. 
+                                                    * This option only has effects for video items of type NERO_NONENCODED_VIDEO_ITEM. */
+	DWORD nwvcdReserved[31];				/* Should be zero */
+	NERO_VIDEO_ITEM nwvcdItems[1];
+} NERO_WRITE_VIDEO_CD;
+
+typedef struct tag_NERO_WRITE_IMAGE
+{
+	char nwiImageFileName[252];				/* Deprecated, use nwiLongImageFileName instead */
+	const char *nwiLongImageFileName;		/* Name of the NRG file to burn
+											   ISO and CUE files can also be burnt this way */
+	NERO_MEDIA_TYPE	nwiMediaType;			/* NeroAPI >= 6.3.0.6: Media on which the image should be written. If set to MEDIA_NONE the default media type of the image will be used. */
+	DWORD nwiReserved[32];
+} NERO_WRITE_IMAGE;
+
+/* This structure will allow you to write any type of 
+ * CD Layout, e.g. containing a raw data track at the beginning of the
+ * disc instead of a self-made ISO/UDF filesystem.
+ * This is good for writing .iso images as they can be downloaded everywhere
+ * on the net */
+typedef struct tag_NERO_WRITE_FREESTYLE_CD
+{
+    DWORD nwfcdStructureSize;                   /* fill this with sizeof(NERO_FREESTYLEWRITE_CD) */
+	/* both may be NULL: */
+	const char *nwfcdArtist;
+	const char *nwfcdTitle;
+
+	struct CNeroIsoTrack *nwfcdIsoTrack;		/* if not NULL, then the disc will have an ISO track - please refer to "NeroIsoTrack.h" */
+	BOOL nwfcdCDExtra;							/* if TRUE and nwfcdIsoTrack not NULL, then the resulting CD will have audio in the first session
+											       and the data track in the second, however, currently the NeroAPI does not add any of the
+												   special CD Extra files to the data track */
+	void *nwfcdpCDStamp;						/* Point on a CDStamp object if a particular CD is requested, otherwise NULL */
+	
+	DWORD nwfcdNumTracks;
+
+	DWORD nwfcdBurnOptions;						/* NeroAPI>=5.5.9.1: Combination of NCITEF flags (ignored if nwfcdFSContainer is NULL) */
+#ifdef __cplusplus
+FileSystemContent::
+#else //__cplusplus
+struct
+#endif//__cplusplus
+    IFileSystemDescContainer *nwfcdFSContainer;	/* NeroAPI>=5.5.9.1: if not NULL, then the disc will have an ISO track described by 
+												   this container. nwfcdIsoTrack must be NULL, otherwise the container will be ignored */
+	NERO_MEDIA_TYPE	nwfcdMediaType;				/* NeroAPI >=5.5.9.1: Media on which the data should be written */
+	DWORD nwfcdReserved[32];					/* Should be zero */
+
+	NERO_FREESTYLE_TRACK nwfcdTracks[1];
+} NERO_WRITE_FREESTYLE_CD;
+
+
+// To burn an IFileSystemDescContainer object
+
+typedef struct tag_NERO_WRITE_FILE_SYSTEM_CONTAINER
+{
+	DWORD nwfscSize;						/* fill this with sizeof(NERO_WRITE_FILE_SYSTEM_CONTENT) */
+#ifdef __cplusplus
+FileSystemContent::
+#else //__cplusplus
+struct
+#endif//__cplusplus
+    IFileSystemDescContainer *nwfscFSContainer;
+	NERO_MEDIA_TYPE	nwfscMediaType;			/* Media on which the data should be written */
+	DWORD nwfscBurnOptions;					/* Combination of NCITEF flags */
+	DWORD nwfscReserved[32];				/* Should be zero */
+} NERO_WRITE_FILE_SYSTEM_CONTENT;
+	
+typedef enum
+{
+	NEROAPI_BURN_OK=0,
+	NEROAPI_BURN_UNKNOWN_CD_FORMAT,
+	NEROAPI_BURN_INVALID_DRIVE,
+	NEROAPI_BURN_FAILED,
+	NEROAPI_BURN_FUNCTION_NOT_ALLOWED,
+	NEROAPI_BURN_DRIVE_NOT_ALLOWED,
+	NEROAPI_BURN_USER_ABORT,
+	NEROAPI_BURN_BAD_MESSAGE_FILE		// message file invalid or missing
+} NEROAPI_BURN_ERROR;
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBurn(NERO_DEVICEHANDLE    aDeviceHandle,
+			 NERO_CD_FORMAT		  CDFormat,
+             const void*		  pWriteCD, // Must point on a NERO_WRITE_CD or a NERO_WRITE_VIDEO_CD structure
+ 			 DWORD                dwFlags,
+             DWORD                dwSpeed,  // In KB/s if NBF_SPEED_IN_KBS is present, in multiple of 150 KB/s otherwise
+             NERO_PROGRESS*       pNeroProgress);
+/* NeroBurn() flags: */
+#define NBF_SPEED_TEST				(1<<0)  /* test speed of source first */
+#define NBF_SIMULATE				(1<<1)  /* simulate writing before actually writing */
+#define NBF_WRITE					(1<<2)  /* really write at the end */
+#define NBF_DAO						(1<<3)  /* write in DAO */
+#define NBF_CLOSE_SESSION			(1<<4)  /* only close the session and not the whole disc */
+#define NBF_CD_TEXT					(1<<5)  /* write CD text - will be ignore if not supported by drive */
+#define NBF_BUF_UNDERRUN_PROT		(1<<6)	/* enable saver burn mode  */
+#define NBF_DISABLE_ABORT			(1<<7)  /* The disable abort callback will be called */
+#define NBF_DETECT_NON_EMPTY_CDRW	(1<<8)	/* The DLG_NON_EMPTY_CDRW user callback will be called when trying to burn onto a non empty CDRW */
+#define NBF_DISABLE_EJECT			(1<<9)	/* CD will not be ejected at the end of the burn process */
+#define NBF_VERIFY                  (1<<10) /* Verify Filesystem after writing. Works for ISO only */
+#define NBF_SPEED_IN_KBS			(1<<11)	/* NeroAPI>=5.5.5.5: Interpret the dwSpeed as KB/s instead of multiple of 150 KB/s */
+#define NBF_DVDP_BURN_30MM_AT_LEAST	(1<<12)	/* NeroAPI>=5.5.8.0: DVD+R/RW high compability mode (at least 1GB will be written) */
+#define NBF_CD_TEXT_IS_JAPANESE		(1<<13) /* NeroApi>=5.5.9.17: If NBF_CD_TEXT and NBF_CD_TEXT_IS_JAPANESE are set, then the CD Text is treated as japanese CD Text */
+#define NBF_BOOKTYPE_DVDROM         (1<<14) /* NeroAPI>5.5.10.7: If NBF_BOOKTYPE_DVDROM the booktype of a burned DVD will be set to DVD-ROM */
+#define NBF_NO_BOOKTYPE_CHANGE		(1<<15) /* NeroAPI>=6.0.0.24: Don't change the booktype of DVD, even if the default setting of NeroAPI is to change the booktype to DVD-ROM*/
+#define NBF_RESERVED3				(1<<29) /* Reserved */
+#define NBF_RESERVED2				(1<<30) /* Reserved */
+#define NBF_RESERVED				(1<<31) /* Reserved */
+
+
+typedef struct tag_NERO_FILESYSTEMTRACK_OPTIONS
+{
+    DWORD				netsStructureSize;		/* fill this with sizeof(NERO_FILESYSTEMTRACK_OPTIONS) */
+
+	/*
+     * The following three entries need to be filled out whenever the file system size is to be calculated
+	 * accurately.
+	 */
+
+	void *				netspCDStamp;			/* Point on a CDStamp object when appending to an existing medium, otherwise NULL */	
+	NERO_MEDIA_TYPE		netsMediaType;			/* The media type the file system is to be written to */
+	NERO_DEVICEHANDLE	netsDeviceHandle;		/* device handle representing the drive the file system is to be written to */
+	DWORD				netsFlags;				/* NBF_XXXX that will be used for the recording process */
+#ifdef __cplusplus
+FileSystemContent::
+#else //__cplusplus
+struct
+#endif//__cplusplus
+    IFileSystemDescContainer *netsFSContainer;	/* if not NULL, the file system will be created from this 
+												 * object instead of the passed CNeroIsoTrack object. pIsoTrack must be NULL in this case */
+	DWORD				netsFSContainerFlags;	/* NCITEF_XXXX flags to be used for filesystem creation. Used only when netsFSContainer 
+												 * is used to create the file system */
+	DWORD netsReserved[32];						/* Should be zero */
+} NERO_FILESYSTEMTRACK_OPTIONS;
+
+
+
+/* NeroAPI >= 6.0.0.14: Estimate the total size of a track including data and overhead
+ * for the filesystem. The method returns the size in blocks.
+ * Use the flags below to specify what exactly has to be taken into account for the
+ * calculation.
+ *
+ * Warning: Depending on the parameters passed, the returned size might only be an estimation!
+ */
+NEROAPI_API unsigned int NADLL_ATTR NeroEstimateTrackSize(struct CNeroIsoTrack *pIsoTrack // the iso track for which to calculate the size
+															   , DWORD dwFlags // combination of the flags below
+															   , NERO_FILESYSTEMTRACK_OPTIONS *pOptions);
+
+#define NETS_FILESYSTEM_OVERHEAD	(1<<0) /* calculate filesystem overhead */
+#define NETS_DATA					(1<<1) /* calculate size of the data */
+#define NETS_EXACT_SIZE				(1<<2) /* Nero >= 6.0.0.21 calculate exactly. 
+											* If this option is specified, filesystem overhead as well as file data is taken into account 
+											* the optional fields of the NERO_ESTIMATETRACKSIZE_OPTIONS structure need to be filled out */
+
+/*
+// Digital Audio Extraction functions:
+// - aborting will not be reported by NeroGetLastError()
+// - incomplete target files are not deleted
+// - the function will return 0 for success, else error
+*/
+
+NEROAPI_API
+int NADLL_ATTR NeroDAE(NERO_DEVICEHANDLE aDeviceHandle,
+			DWORD             dwTrackStartBlk,
+			DWORD             dwTrackLengthInBlks,
+            const NERO_DATA_EXCHANGE *pDestDataExchg,
+            DWORD             iSpeedInX,				// speed of extraction, 0 means maximum speed
+            NERO_CALLBACK*    pNeroProgressCallback); /* has to be a NERO_PROGRESS_CALLBACK */
+
+
+//
+// Utility functions:
+//
+NEROAPI_API int NADLL_ATTR NeroIsDeviceReady(NERO_DEVICEHANDLE aDeviceHandle); // returns a value of NERO_DRIVE_ERROR
+NEROAPI_API int NADLL_ATTR NeroEjectLoadCD(NERO_DEVICEHANDLE aDeviceHandle,BOOL eject);	// returns a value of NERO_DRIVE_ERROR
+
+// NeroAPI >= 6.6.0.2: waits dwTimeOut milliseconds until a drive is ready. returns a value of NERO_DRIVE_ERROR
+NEROAPI_API int NADLL_ATTR NeroWaitForDeviceReady(NERO_DEVICEHANDLE aDeviceHandle, DWORD dwTimeOut, void *reserved);
+
+// NeroAPI >= 6.0.0.25:
+// Set the image file for the image recorder. This can be used to initialize
+// the image recorder for packet writing.
+// If imageFilePath is NULL, the last opened file is closed.
+NEROAPI_API int NADLL_ATTR NeroInitImageRecorder(NERO_DEVICEHANDLE aDeviceHandle, const char *imageFilePath, DWORD dwFlags, NERO_MEDIA_TYPE mediaType, void *reserved);
+
+
+// NeroAPI>=5.5.9.10: Get localized WAIT_CD text
+//	Returned string must be released using NeroFreeMem()
+//	Function may return NULL if type is out of range
+NEROAPI_API char * NADLL_ATTR NeroGetLocalizedWaitCDTexts (NERO_WAITCD_TYPE type);
+
+	
+// NeroAPI >= 6.0.0.25: Use the nstUserDialog callback functions to request a CD
+// Returns FALSE if the burn process should be aborted
+NEROAPI_API BOOL NADLL_ATTR NeroWaitForDisc(NERO_DEVICEHANDLE aDeviceHandle
+											 ,NERO_MEDIA_SET nmt	// media types requested
+											 ,DWORD dwBurnFlags		// Set of NBF_ flags
+											 ,void *pCDStamp		// Optional stamp of requested media
+											 ,DWORD dwFlags			// Set of NWFD_ flags
+											 ,void *reserved);	    // must be NULL
+#define NWFD_REQUIRE_EMPTY_DISC (1<<0)
+
+
+// CDRW erasing functions
+
+typedef enum 
+{
+	NEROAPI_ERASE_ENTIRE	=0,
+	NEROAPI_ERASE_QUICK		=1,
+} NEROAPI_CDRW_ERASE_MODE;
+
+
+// Returns estimated blanking time for loaded CD-RW in seconds, 
+// -1 if no CD inserted, 
+// -2 if recorder doesn't support CDRW
+// -3 if the inserted media is not rewritable (NeroAPI>=5.5.7.4)
+
+//
+//  Deprecated. Please use NeroGetDiscErasingTime instead.
+//
+NEROAPI_API int NADLL_ATTR NeroGetCDRWErasingTime(NERO_DEVICEHANDLE aDeviceHandle,NEROAPI_CDRW_ERASE_MODE mode);
+
+// NeroAPI >= 6.6.1.0
+// Get rewritable disc erasing time corresponding to the erasing speed in KB/s
+NEROAPI_API int NADLL_ATTR NeroGetDiscErasingTime(NERO_DEVICEHANDLE aDeviceHandle,
+						  NEROAPI_CDRW_ERASE_MODE mode,
+						  DWORD dwSpeedInKBs);
+
+// Erase the disc inserted in the given recorder
+// May return error codes of the method above or NERO_DRIVE_ERROR
+NEROAPI_API int NADLL_ATTR NeroEraseDisc(NERO_DEVICEHANDLE aDeviceHandle,
+					 NEROAPI_CDRW_ERASE_MODE mode,
+					 DWORD dwFlags,
+					 DWORD dwSpeedInKBs);
+#define NEDF_DISABLE_EJECT			(1<<0)	/* NeroAPI>=6.0.0.0: CD will not be ejected at the end of the 
+												erasing, even if this is recommanded for the selected recorder*/
+#define NEDF_EJECT_AFTER_ERASE		(1<<1)  /* NeroAPI > 6.0.0.0: eject disc after erasing, no matter if this is 
+											   recommended for the recorder or not */
+
+typedef enum
+{
+	NFSNT_Filename,			// filename
+	NFSNT_Dirname,			// directory name (ISO9660 has different naming conventions for file and directory names.)
+	NFSNT_VolumeLabel		// volume lable
+} NERO_FS_NAMETYPE;
+
+typedef enum
+{
+	NFST_ISO,				// ISO 9660
+	NFST_UDF,				// UDF
+	NFST_JOLIET,			// Joliet
+	NFST_JOLIET_RELAXED,
+	NFST_UDF_DVDVIDEO,		// DVD-Video compatible UDF
+	NFST_ROCKRIDGE			// Rockridge
+} NERO_FS_TYPE;
+
+/*
+// NeroAPI>=6.6.0.4: 
+// Convert a given filename/volume label to a valid filename for a certain filesystem
+// returns TRUE, if the filename is converted, false otherwise
+// if out is NULL, it returns TRUE, if the filename needs conversion
+*/ 
+NEROAPI_API  BOOL NADLL_ATTR NeroConvertToValidFileSystemName(const WCHAR *in // the filename/volume label to convert
+					, WCHAR *out					// the buffer that will receive the converted filename
+					, unsigned long outBufferSize	// the size of buffer out in bytes
+					, NERO_FS_NAMETYPE nameType		// the type of the name (filename or volume label)
+					, NERO_FS_TYPE dwFilesystemFlag // For which filesystem the name is to be converted
+					, void *reserved);				// reserved for future use; has to be NULL
+
+
+
+typedef enum
+{
+   NDR_DRIVE_IN_USE=0,
+   NDR_DRIVE_NOT_IN_USE,
+   NDR_DISC_REMOVED,
+   NDR_DISC_INSERTED,
+   NDR_DRIVE_REMOVED,
+   NDR_DRIVE_ADDED
+} NERO_DRIVESTATUS_RESULT;
+
+/* 
+// callback that is called to tell the application about a status change of a drive 
+// hostID corresponds to the nsdiHostAdapterNo and targetID corresponds 
+// to the nsdiDeviceID of NERO_SCSI_DEVICE_INFO
+// Note: The callback need to be thread safe, since it might be called from a different thread
+*/
+typedef void  (NERO_CALLBACK_ATTR *NERO_DRIVESTATUS_CALLBACK)(int hostID, int targetID, NERO_DRIVESTATUS_RESULT result, void *pUserData);
+
+typedef enum
+{
+   // the disc in the drive has been changed
+   // Warning: This change notification is based on Windows notifying about
+   // medium changes. If an application has disabled this notification, the
+   // callback will not be called. If you want to be sure to recognize all 
+   // medium changes, you should use timer events and use NeroIsDeviceReady
+   // to ask for the drive status.
+   NDT_DISC_CHANGE, 
+   NDT_IN_USE_CHANGE  // the in-use status of the drive has been changed
+} NERO_DRIVESTATUS_TYPE;
+
+/* NeroAPI >= 6.0.0.0: 
+// Register a callback which is called whenever the specified status
+// of a drive is changed.
+//
+// Please see documentation of NERO_DRIVE_STATUS_TYPE for restrictions of the
+// notifications.
+//
+//
+// Parameters:
+// status: the status the application is interested in
+// pDeviceInfo: the drive for which the status change should be notified.
+//              The pointer can be freed afterwards.
+// callback: the callback to be called if the status changed. 
+// Note: The callback need to be thread safe, since it might be called from a different thread
+// pUserData: data passed to the callback
+//
+// returns 0 on success
+*/
+NEROAPI_API int NADLL_ATTR NeroRegisterDriveStatusCallback(NERO_DRIVESTATUS_TYPE status 
+													 , const NERO_SCSI_DEVICE_INFO *pDeviceInfo  
+													 , NERO_DRIVESTATUS_CALLBACK callback 
+													 , void *pUserData);
+
+/* NeroAPI >= 6.0.0.0: 
+// Unregister a callback
+//
+// Parameters:
+// status: the status for which the callback has been registered
+// pDeviceInfo: the drive for which the status was notified
+//              The pointer does not need to be the same as in
+//              NeroRegisterDrivestatusCallback, but has to represent
+//              the same drive.
+// callback: the callback to be called if the status changed.
+// pUserData: data passed to the callback
+//
+// returns 0 on success
+*/
+NEROAPI_API int NADLL_ATTR NeroUnregisterDriveStatusCallback(NERO_DRIVESTATUS_TYPE status // the status the application is interested in
+													 , const NERO_SCSI_DEVICE_INFO *pDeviceInfo  // the drive for which the status should be acknowledged
+													 , NERO_DRIVESTATUS_CALLBACK callback // the callback to be called if the status changed
+													 , void *pUserData); // data passed to the callback
+
+/*
+// NeroAPI >= 6.0.0.0:
+// Register a callback which is called whenever a drive was removed or added in the system
+// Use NeroGetAvailableDrivesEx to get the current list of drives in the system.
+//
+// NOTE: In some rare cases NeroAPI does not get this information from the OS and will therefore
+//       never notify the callback if a drive has been added/removed.
+//
+// Parameters:
+// callback: the callback to be called when a drive is removed or added
+//    Note: The callback need to be thread safe, since it might be called from a different thread
+// pUserData: data passed to the callback
+//
+// returns 0 on success
+*/
+NEROAPI_API int NADLL_ATTR NeroRegisterDriveChangeCallback( NERO_DRIVESTATUS_CALLBACK callback
+													 , void *pUserData);
+
+/*
+// NeroAPI >= 6.0.0.0:
+// Unregister a callback which was registered with NeroRegisterDriveChangeCallback
+//
+// Parameters:
+// callback: the callback to be called when a drive is removed or added
+// pUserData: data passed to the callback
+//
+// returns 0 on success
+*/
+NEROAPI_API int NADLL_ATTR NeroUnregisterDriveChangeCallback(NERO_DRIVESTATUS_CALLBACK callback
+													 , void *pUserData); 
+
+
+// NeroAPI > 5.5.9.8: AUDIO SUPPORT
+
+
+// NERO_CONFIG_RESULT
+
+typedef enum
+{
+	NCR_CANNOT_CONFIGURE,
+	NCR_CHANGED,
+	NCR_NOT_CHANGED
+} NERO_CONFIG_RESULT;
+
+////////////////////////////////////////////////////// NERO_AUDIO_FORMAT_INFO //
+
+typedef struct tagNERO_AUDIO_FORMAT_INFO
+{
+// Data
+	// smth. like "RIFF PCM WAV format"
+	char	nafiDescription[256],
+
+	// smth. like "wav,wave,riff"
+			nafiExtList[256];
+
+	BOOL	nafiTgt,				// Contains TRUE if this is a target plugin
+			nafiConfigurable;	// ConfigureItem will fail on items of
+								// this type if this member == false
+}
+	NERO_AUDIO_FORMAT_INFO;
+
+//////////////////////////////////////////////////////////// Helper functions //
+
+NEROAPI_API NERO_AUDIO_ITEM_HANDLE	NeroAudioCreateTargetItem(int iFormatNumber);
+
+NEROAPI_API BOOL				NeroAudioCloseItem(NERO_AUDIO_ITEM_HANDLE hItem);
+
+// Insead of hItem a value of NULL can be passed to configure the
+// whole plugin manager.
+NEROAPI_API NERO_CONFIG_RESULT	NeroAudioGUIConfigureItem		\
+									(NERO_AUDIO_ITEM_HANDLE *phItem, int iNum);
+
+// As soon as it returns false, it means that there are no more formats.
+NEROAPI_API BOOL				NeroAudioGetFormatInfo			\
+									(int iNum, NERO_AUDIO_FORMAT_INFO *pFI);
+
+//
+// Deprecated functions. Present for compatibility with previous versions
+//
+
+NEROAPI_API DWORD NADLL_ATTR NeroGetAPIVersion(void);  /* Returns 1000 for 1.0.0.0 */
+
+NEROAPI_API BOOL NADLL_ATTR NeroSetExpectedAPIVersion(DWORD);
+
+NEROAPI_API NERO_ISO_ITEM *NeroImportIsoTrackEx(NERO_DEVICEHANDLE pRecorder,
+						     DWORD trackNumber,
+						     void **ppCDStamp,
+						     DWORD flags);
+
+NEROAPI_API int NADLL_ATTR NeroEraseCDRW(NERO_DEVICEHANDLE aDeviceHandle,NEROAPI_CDRW_ERASE_MODE mode);			// Erase the loaded CD
+
+
+// NeroAPI>=5.5.9.4: Use the nstUserDialog callback functions to request a CD
+// Returns FALSE if the burn process should be aborted
+NEROAPI_API BOOL NADLL_ATTR NeroWaitForMedia(NERO_DEVICEHANDLE aDeviceHandle
+											 ,NERO_MEDIA_SET nms			// media types requested
+											 ,DWORD dwFlags					// Set of NBF_ flags
+											 ,void *pCDStamp);				// Optional stamp of requested media
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+#endif  // _NEROAPI_
+
+//======================================================
+// NeroApi.h
+//======================================================
+
+

+ 72 - 0
Burndiscs/Burndiscs/Nero/Include/NeroAPIGlue.h

@@ -0,0 +1,72 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroAPIGlue.h
+|*
+|* PURPOSE: Functions for connecting to NeroAPI
+******************************************************************************/
+
+
+#ifndef __NEROAPIGLUE__
+#define __NEROAPIGLUE__
+
+#ifdef _NEROAPI_
+#	pragma message("WARNING: Include 'NeroAPIGlue.h' BEFORE any other headers of the NeroAPI!")
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+// All functions in NeroAPI.h are implemented here, too:
+*/
+
+#include "NeroAPI.h"
+
+#define USING_NEROSDK
+
+/*
+// This function has to be called first.
+*/
+
+BOOL NADLL_ATTR NeroAPIGlueConnect (void *reserved);
+
+/*
+// This one cleans up after using the glue code.
+*/
+void NADLL_ATTR NeroAPIGlueDone (void);
+
+
+// Returns the module handle of the loaded NeroAPI
+HMODULE NADLL_ATTR NeroAPIGlueGetModuleHandle();
+
+
+// Attach an already loaded NeroAPI module
+// Do NOT call NeroAPIGlueDone after this method. This should only be called
+// from the part of the application that called NeroAPIGlueInitEx or 
+// NeroAPIGlueConnect
+//
+// NOTE: This method does not set the expected version of the NeroAPI.
+// This is only done when the glue layer is initialized with NeroAPIGlueConnect
+// or NeroAPIGlueInitEx
+// Therefore, if you attach a NeroAPI module you should always set the
+// expected version of NeroAPI before calling a NeroAPI method and restore the
+// previously set version afterwards.
+BOOL NADLL_ATTR NeroAPIGlueAttachModule(HMODULE hNeroAPI,void *reserved);
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+
+#endif /* __NEROAPIGLUE__ */
+

+ 180 - 0
Burndiscs/Burndiscs/Nero/Include/NeroBurnAtOnce.h

@@ -0,0 +1,180 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroBurnAtOnce.h
+|*
+|* PURPOSE: Interface to BurnAtOnce functionality of Nero API.
+|*          BurnAtOnce can burn DVD-Video data directly to DVDs without having
+|*          to first generate all files on the harddisc.
+|*
+|* NOTES  : This functionality is present up from NeroAPI 6.3.1.11
+******************************************************************************/
+#ifndef NEROBURNATONCE_H
+#define NEROBURNATONCE_H
+
+#include "NeroAPI.h"
+
+#ifdef __cplusplus
+
+#include "NeroFileSystemContent.h"
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+namespace FileSystemContent
+{
+	// ask the IDataInputStream object you get in IFileProducer::ProduceFile
+	// with GetOtherInterface("IBurnAtOnceInfo") to get a pointer to this object
+	class IBurnAtOnceInfo : public InterfaceBase
+	{
+	public:
+		// returns the offset to start of VIDEO_TS.IFO in blocks
+		virtual DWORD GetOffset() const = 0;
+	};
+}
+#endif // __cplusplus
+
+#ifdef __cplusplus
+class CBurnAtOnceRecorder;
+typedef CBurnAtOnceRecorder* NERO_BAO_HANDLE;
+
+extern "C"
+{
+
+#else // __cplusplus
+typedef void* NERO_BAO_HANDLE;
+#endif 
+		   
+
+typedef struct tag_NERO_BURN_AT_ONCE
+{
+	/* fill this with sizeof(NERO_BURN_AT_ONCE) */
+	DWORD nwbaoSize;				
+
+	/* path to a directory to store temporary files
+	 * If NULL, system temp directory will be used */
+	const char *nwbaoTempDirectory; 
+
+	/* The content of the filesystem 
+	 * Important:
+	 * 1) All IFO and BUP files must have set the exact file size
+	 * 2) All other video files must have set the estimated size which will be 
+	 *    updated during burning. Note, that the estimated size should
+	 *    be as exact as possible.
+	 * 3) For each video title set only add the first VOB file (e.g. VTS_01_1.VOB)
+	 *    to the file system container and pass all the video data of this title set
+	 *    in the file producer of this file. NeroAPI will automatically split the 
+	 *    file at the appropriate size (1 GB - logical block size).
+	 * 4) DVD-Video files will be sorted automatically
+	 * 5) It is guaranteed that the file data will be requested in the following order:
+	 *    - VMGM_VOB (VIDEO_TS.VOB) [if present]
+	 *    - For each video title set (VTS):
+	 *      - VTSM_VOB (e.g. VTS_01_0.VOB) [if present]
+	 *      - VTSTT_VOBS (e.g. VTS_01_1.VOB) [mandatory]
+	 *      - VTSI file (e.g. VTS_01_0.IFO)  [mandatory]
+	 *      - VTSI backup (e.g. VTS_01_0.BUP) [mandatory]
+	 *    - VMGMI (VIDEO_TS.IFO) [mandatory]
+	 *    - Backup for VMGMI (VIDEO_TS.BUP) [mandatory]
+	 */
+#ifdef __cplusplus
+FileSystemContent::
+#else //__cplusplus
+struct
+#endif//__cplusplus
+    IFileSystemDescContainer *nwbaoFSContainer;	
+
+	DWORD nwbaoReserved[64];				/* Should be zero */
+} NERO_WRITE_BURN_AT_ONCE;
+	
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBurnAtOnce(NERO_DEVICEHANDLE    aDeviceHandle,
+             NERO_WRITE_BURN_AT_ONCE *pBurnAtOnce,
+ 			 DWORD                dwFlags,	// set of NBF_ flags. Note, that not all NBF_ flags will be interpreted.
+             DWORD                dwSpeed,  // In KB/s if NBF_SPEED_IN_KBS is present, in multiple of 150 KB/s otherwise
+             NERO_PROGRESS*       pNeroProgress,
+			 void *reserved);
+
+
+/* This is the second method to do BurnAtOnce with NeroAPI.
+ * It allows more control by application but you have to make sure
+ * by yourself to deliver the data in the correct order. Additionally,
+ * NeroAPI will not cache any data in memory with this method and the
+ * methods block until all the data is written. Therefore, your
+ * application should implement some caching itself for performance reasons.
+ *
+ * Howto use:
+ * 1) Fill the nwbaoFSContainer of NERO_WRITE_BURN_AT_ONCE to specify the 
+ *    layout of the DVD.
+ * 2) Call NeroBAOCreateHandle with the necessary information to get a NERO_BAO_HANDLE
+ * 3) For each video file in the VIDEO_TS folder, call NeroBAOOpenFile, then write
+ *    all the data with NeroBAOWriteToFile and then call NeroBAOCloseFile. 
+ *    Note:
+ *    it is absolutely important, that this is done in the correct order. See
+ *    notes on the nwbaoFSContainer above.
+ * 4) After all video data is written, call NeroBAOCloseHandle. This will write additional
+ *    files that are present in the filesystem container and then finalize the disc.
+ * 5) If an error occurs on your side and/or you want to cancel burning, just call
+ *    NeroBAOCloseHandle with dwFlags set to NBAOF_CANCELED or NBAOF_FAILED.
+ * 6) If an error occurs on NeroAPI's side, also call NeroBAOCloseHandle to end burning
+ *    and do some cleanup.
+ *
+ * Notes:
+ * - nwbaoFSContainer needs to be valid until NeroBAOCloseHandle is called.
+ */
+
+NEROAPI_API 
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBAOCreateHandle(NERO_DEVICEHANDLE aDeviceHandle,
+			NERO_WRITE_BURN_AT_ONCE *pBurnAtOnce,
+			DWORD                dwFlags,	// set of NBF_ flags. Note, that not all NBF_ flags will be interpreted.
+			DWORD                dwSpeed,  // In KB/s if NBF_SPEED_IN_KBS is present, in multiple of 150 KB/s otherwise
+			NERO_PROGRESS*       pNeroProgress,
+			NERO_BAO_HANDLE* pBAOHandle, // will get the handle created by NeroAPI
+			void *reserved);
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBAOOpenFile(NERO_BAO_HANDLE hBAOHandle, const char *name, DWORD* pdwOffset, void *reserved);
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBAOWriteToFile(NERO_BAO_HANDLE hBAOHandle, 
+			const void* lpBuffer, // data buffer
+			DWORD nNumberOfBytesToWrite, // number of bytes to write
+			                             // Must be multiple of 2048!
+			LPDWORD lpNumberOfBytesWritten,
+			void *reserved);
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBAOCloseFile(NERO_BAO_HANDLE hBAOHandle,
+			void *reserved);
+
+
+NEROAPI_API
+NEROAPI_BURN_ERROR NADLL_ATTR NeroBAOCloseHandle(NERO_BAO_HANDLE hBAOHandle, DWORD dwFlags, void *reserved);
+
+#define NBAOF_CANCELED (1<<0)
+#define NBAOF_FAILED   (1<<1)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+
+#endif // NEROBURNATONCE_H

+ 84 - 0
Burndiscs/Burndiscs/Nero/Include/NeroCopyAPI.h

@@ -0,0 +1,84 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroCopyAPI.h
+|*
+|* PURPOSE: interface for Nero Copy API
+******************************************************************************/
+#ifndef _NEROCOPYAPI_
+#define _NEROCOPYAPI_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "NeroAPI.h"
+
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+/*
+ *	To copy a disc with NeroAPI, fill in the structure 
+ *  NERO_CD_COPY, pass it to NeroBurn as parameter pWriteCD
+ *  and set CDFormat to  NERO_CD_COPY_TYPE.
+ */
+
+#define NERO_CD_COPY_TYPE	((NERO_CD_FORMAT)1000)
+
+typedef struct
+{
+	NERO_DEVICEHANDLE sourceDrive; // The drive to read the data from
+	BOOL onTheFly; // copy on-the-fly (without storing an image on the harddrive first)
+	const char *imageFilePath; // for non on-the-fly copying, specify the temporary imagefile path here (mandatory)
+	BOOL deleteImage; // should the temporary image deleted after burning or not
+	
+	int readSpeed;	// Read speed in KB/s, 0 for maximum speed
+	
+	UINT tryNr;	// number of tries, if read error appeared
+	BOOL readErrOption; // for data tracks: 1: ignore read errors and continue; 0: abort on read errors
+
+	// for NeroAPI 5.5 it was possible to select the readRaw mode for Mode1 and Mode2 separately.
+	// up from NeroAPI 6, general read raw mode is enable if one of these options is set
+	BOOL readRawMode1; // read raw mode
+	int rawMode1Option; // for NeroAPI 6: ignored; for NeroAPI 5.5: 0: Repair EDC/ECC error for raw data, 1: Ignore EDC/ECC error for raw data
+	BOOL readRawMode2; // read raw mode
+	int rawMode2Option; // for NeroAPI 6: ignored; for NeroAPI 5.5: 0: Repair EDC/ECC error for raw data, 1: Ignore EDC/ECC error for raw data
+
+	BOOL readSub; // For NeroAPI 6: ignored, for NeroAPI 5.5: read audio data with sub q code
+	BOOL checkDA; // For NeroAPI 6: ignored, for NeroAPI 5.5: check for audio data
+	int slowDown; // For NeroAPI 6: ignored, for NeroAPI 5.5 option for jitter correction in read audio track: 0: If correction failed rewind and read from beginning, 1: If correction failed slow down at once, 2: no jitter correction
+	BOOL ignoreDAErr; // for audio tracks: ignore read errors and continue 
+	BOOL readIsrcAndMediaCatalogNo; // NeroAPI 5.5 and NeroAPI >= 6.3.1.24: TRUE if media catalog number and ISRC should be read and copied
+	BOOL ignoreBadTOCType; // for NeroAPI 6: ignored, for NeroAPI 5.5: should be set to TRUE
+
+	NERO_MEDIA_TYPE mediaType; // NeroAPI >= 6.3.1.24: which media type is to be copied
+} NERO_CD_COPY;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+#endif  // _NEROCOPYAPI_
+
+//======================================================
+// NeroCopyApi.h
+//======================================================

+ 298 - 0
Burndiscs/Burndiscs/Nero/Include/NeroFileSystemContent.h

@@ -0,0 +1,298 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroFileSystemContent.h
+|*
+|* PURPOSE: 
+|* This is the third NeroAPI interface for preparing data CDs/DVDs. Unlike NeroIsoTrack.h,
+|* it is not much "callback based",thus most of the process will be driven by the 
+|* application, making it easier to write. This interface is closely connected to the
+|* internal engine of NeroAPI, this improves the cooperation of NeroAPI and the application.
+|*
+|* This set of classes describe the content of the file system of a disc.
+|* The application will build a file structure using the IFileSystemContent object. 
+|* During the burn process, NeroAPI will request the content of files using the 
+|* IFileContent interface.
+|*
+|* Use the NeroCreateFileSystemContainer function of NeroAPI.h to get an instance of an
+|* IFileSystemDescContainer object. Then, use the NERO_WRITE_FILE_SYSTEM_CONTAINER structure 
+|* to burn the file structure created.
+******************************************************************************/
+#ifndef __NEROFILESYSTEMCONTENT_H
+#define __NEROFILESYSTEMCONTENT_H
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+
+// To make sure we do not interfere with other classes
+namespace FileSystemContent
+{
+
+class InterfaceBase
+{
+public:
+	// Get another interface for the same object. This will be used to extend the DLL interface without
+	// loosing binary compatibility. Returns NULL if no interface with this ID was found
+	// This is inspired from the COM QueryInterface function
+	virtual void *GetOtherInterface(int interfaceId)			const	// Using an ID number
+	{
+		return 0;	// Not other interface available by default
+	}
+	virtual void *GetOtherInterface(const char *interfaceName)	const	// Using a string
+	{
+		return 0;	// Not other interface available by default
+	}
+
+protected:
+	virtual ~InterfaceBase()	{}
+};
+
+////////////////////////////////////////////////////////////////////////////////////////
+// This first set of interfaces will be used by the burn engine to read the content of
+// the file system
+////////////////////////////////////////////////////////////////////////////////////////
+
+class IFileContent : public InterfaceBase
+{
+public:
+	virtual unsigned Read(void *pBuffer,unsigned length)	=0;
+	virtual bool EndOfFile()								=0;
+	virtual bool Error()									=0;
+
+	// Called by the application when the object is not needed anymore
+	virtual void Release()									= 0;
+};
+
+class IDirectory;
+
+class IDirectoryEntry : public InterfaceBase
+{
+public:
+	enum ENTRY_ERROR
+	{
+		ENTRY_NO_ERROR,
+		SEQUENCING_ERROR,		// The content for this file may not be requested at this moment	
+		ERROR_NOT_A_FILE,		// This entry is not a file 
+		NOT_AVAILABLE,			// The content of this file cannot be requested at all
+		INTERFACE_ERROR,		// The overriden function has tried to get an other interface for one object and has failed
+		FEATURE_NOT_AVAILABLE	// This feature is not available for this file system type
+	};
+
+	enum {
+		MODE2_FORM2					=1<<0,
+		FIXED_INSIDE_VOLUME_SPACE	=1<<1,
+		FIXED_OUTSIDE_VOLUME_SPACE	=1<<2,
+		NO_OWN_CONTENT				=1<<3,
+		CPR_MAI_ADPTY				=1<<4
+	};
+		
+	virtual const char *GetName()					const	=0;	// File or directory name
+
+	virtual const IDirectory *GetSubDirectory()		const	=0;
+	virtual ENTRY_ERROR GetContent(IFileContent **)	const	=0;
+	virtual const char *GetSourceFilePath()			const	=0;	// Return the source file path, NULL if the file is generated
+	virtual __int64	GetSize()						const	=0;
+	virtual int GetFilePriority()					const   =0;
+	virtual int GetDirOrder()						const   =0;
+	virtual int	GetId()								const	=0;	// Id number that can be used to find the file again later
+	virtual unsigned GetDataStartSec()				const	=0;
+};
+
+class IDirectory : public InterfaceBase
+{
+public:
+	virtual int GetNumEntries()								const =0;
+	virtual const IDirectoryEntry *GetDirectoryEntry(int i)	const =0;
+};
+
+
+class IFileSystemContent : public InterfaceBase
+{
+public:
+	virtual const char *GetName()							const =0;	// Volume name
+	virtual const IDirectory *GetRoot()						const =0;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// This second set of interfaces will be used by the application to produce the content of
+// the file system
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+// Allows the file producer to return the data
+class IDataInputStream : public InterfaceBase
+{
+public:
+	virtual void Write(const void *buffer,int size)								 = 0;
+};
+
+// Produce the content of a file. This interface must be derived and its implementation must
+// create the content of the file in the ProduceFile function
+class IFileProducer : public InterfaceBase
+{
+public:
+	// Calling this method will automatically update the file size to the amount of data
+	// delivered by the producer
+	virtual IDirectoryEntry::ENTRY_ERROR ProduceFile(IDataInputStream *str) const = 0;
+
+	// Called by NeroAPI when the object is not needed anymore
+	virtual void Release()													const = 0;
+};
+
+
+class IDirectoryContainer;
+
+// Description of a file
+class IDirectoryEntryContainer : public IDirectoryEntry
+{
+public:
+	// This object can be accessed in several ways
+	enum
+	{
+		IID_IDirectoryEntryContainer,
+		IID_IFileProducer,				// If the file entry was created using an IFileProducer 
+										// object, this one can be retrieved using GetOtherInterface
+		IID_IDirectoryEntryContainer2,	// Reserved
+		IID_IDirectoryEntry2			// Reserved
+	};
+
+	// Using this function, the file size can be changed after having added the entry to the directory
+	virtual void SetSize(__int64 size)						=0;
+
+	// The two functions below can be used to readjust the directory priority
+	// Priority numbers will be used in upward order: the file with smaller values first
+	virtual void SetPriority(int priority)					=0;
+	virtual void SetDirOrder(int directoryPriority)			=0;
+
+	// Set the sector number that will be saved into the directory structure
+	virtual void SetDataStartSec(unsigned)					=0;	
+
+	// Set the physical position of the file in the filesystem
+	virtual void SetFixedDataStartSec(unsigned)				=0;
+
+	virtual void SetFileNumber(int)							=0;
+	virtual void SetId(int)									=0;
+	virtual void SetFlags(bool enable,unsigned f)			=0;	// Enable/disable the given flag
+};
+
+// Extension of the IDirectoryEntryContainer interface
+class IDirectoryEntryContainer2 : public IDirectoryEntryContainer
+{
+public:
+	// If the file entry was created using an IFileProducer, returns a pointer on it
+	virtual const IFileProducer *GetFileProducer() const			=0;
+
+	// Update the size attribute of this file by producing its content without writing
+	// it anywhere
+	virtual ENTRY_ERROR MeasureSize()								=0;
+
+	// Set the size that is stored in the media directory record but do not change the
+	// size of allocated and requested data 
+	// This is currently only available for ISO filesystems
+	virtual ENTRY_ERROR SetDirRecordSize(__int64 size)						=0;
+};
+
+
+// Represents the content of a directory
+class IDirectoryContainer : public IDirectory
+{
+public:
+	// Add a directory a returns a pointer on it
+	// directoryPriority specifies the position in the directory. See this->AddFile
+	// for details
+	virtual IDirectoryContainer *AddDirectory(const char *name, int directoryPriority) =0;
+
+	// Add a file the directory. The fp object will be automatically deleted when the directory
+	// container will be deleted
+	// 
+	// the filesize passed here does *not* need to be correct, it will be used by the
+	// filesystem generator to preallocate space so it must be the *maximum* space the final
+	// version of the file may need (worst-case).
+	//
+	// Priority specifies some user-defined ordinal defining the order in which the files are
+	// being written to the disc physically (like .ifo comes before .vob).
+	// Priorities are valid across directories
+	// The fileentry order in a directory is defined by the directoryPriority parameter which is the primary
+	// sort criterium when arranging the files in a directory (Note that this is only true for
+	// filesystems that do not require files to be sorted in the directory, e.g. UDF)
+	// If any of the priority specifiers is -1, the producer doesn't care about the priority
+	// and Nero will put the file where it thinks it fit
+	// AddFile will return NULL if a file with the same name already exists
+	virtual IDirectoryEntryContainer *AddFile(const char *name,
+											  const IFileProducer *fp,__int64 size,
+											  int priority, int directoryPriority) = 0;										 
+
+	// Add a file which exists in the real file system
+	virtual IDirectoryEntryContainer *AddFile(const char *name,
+											  const char *sourcePath,
+											  int priority, int directoryPriority) = 0;										 
+	
+	// Remove an entry from the directory
+	virtual bool RemoveEntry(const char *name)								=0;
+
+	virtual IDirectoryEntryContainer *Entry(const char *name)				=0;
+	virtual IDirectoryEntryContainer *Entry(int i)							=0;
+	virtual IDirectoryContainer *SubDirectory(const char *name)				=0;
+};
+
+
+// Supplemental method to the IDirectoryContainer interface
+class IDirectoryContainerSearch {
+	public:
+		enum {
+			SEARCH_DEPTH_INCL,   // Searches whole tree including given start object
+			SEARCH_CHILDREN_EXCL // Searches children of start object only
+		};
+		// Like 'SubDirectory' of 'IDirectoryContainer' but with different search modes.
+		// 'reserved' is intended for future use and MUST be initialized with NULL for now.
+		virtual IDirectoryContainer *SubDirectoryEx(const char *name, unsigned mode, void *reserved) = 0;
+};
+
+
+// Represents the content of a file system
+struct IFileSystemDescContainer : public IFileSystemContent
+{
+	virtual void SetName(const char *)	=0;		// Set the volume name of the file system
+	virtual IDirectoryContainer *Root()	=0;		// Access the root directory for changing it
+
+	// Called by the application when the object is not needed anymore
+	virtual void Release()													const = 0;
+};
+
+// Extension of IFileSystemDescContainer to set extended volume names.
+// If you use these methods, don't use SetName of  IFileSystemDescContainer
+struct IFileSystemDescContainerVolume : public InterfaceBase
+{
+	virtual void SetISOName(const char *) = 0;
+	virtual void SetJolietName(const WCHAR *) = 0;
+	virtual void SetUDFName(const WCHAR *) = 0;
+
+	// Non-const get functions will return a volume label even if it was
+	// not set by calling above methods. These methods will provide a volume label
+	// that will be really burn on the disc by converting illegal characters.
+	virtual const char*  GetISOName() = 0;
+	virtual const WCHAR* GetJolietName() = 0;
+	virtual const WCHAR* GetUDFName() = 0;
+};
+
+} // namespace FileSystemContent
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop
+#endif
+
+#endif//__NEROFILESYSTEMCONTENT_H

+ 69 - 0
Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockAccessExtensions.h

@@ -0,0 +1,69 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: FileSystemBlockAccessExtensions.h
+|*
+|* PURPOSE: All block device access extensions are derived from this one.
+|*
+******************************************************************************/
+#ifndef FILESYSTEMBLOCKACCESSEXTENSIONS_H
+#define FILESYSTEMBLOCKACCESSEXTENSIONS_H
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+/* 
+ * Type of an extension.
+ * Currently no extension is provided within the NeroSDK
+ */
+enum NeroFSBlockAccessExtensionsType
+{
+	etMRWReadDefectiveManagementInfo,
+	etDVDPRWFormatExtension,
+	etSectorMappingControlExtension,
+	etBlankAreaControlExtension,
+	etIllegalBlockAccessExtension,
+	etHDPartitionInfo,
+	etHDUsedBlockAccessExtention,
+	etSectorPatchControlExtension,
+	etHDPartitionLocker,
+	etMediumCDStamp,
+	etFragmentReservation,
+	etUDFImageEditExtension,
+	etSessionControl,
+	etNeroFSBAExtensionReserved1,
+	etNeroFSBAExtensionReserved2,
+	etMediumInfo,
+	etNeroFSBAExtensionReserved3,
+	etNeroFSBAExtensionReserved4,
+	etNeroFSBAExtensionReserved5,
+	etNeroFSBAExtensionReserved6
+};
+
+class INeroFileSystemBlockAccessExtension
+{
+public:
+	virtual NeroFSBlockAccessExtensionsType GetExtensionType() const = 0;
+
+	virtual ~INeroFileSystemBlockAccessExtension() {}; 
+};
+
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+
+#endif // FILESYSTEMBLOCKACCESSEXTENSIONS_H

+ 44 - 0
Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockAccessInterface.h

@@ -0,0 +1,44 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: FileSystemBlockAccessInterface.h
+|*
+|* PURPOSE: The file system block access interface
+|* The NeroAPI packet writing API will return INeroFileSystemBlockAccess that
+|* can be used to have block access to a file system.
+******************************************************************************/
+#ifndef FILESYSTEMBLOCKACCESSINTERFACE_H
+#define FILESYSTEMBLOCKACCESSINTERFACE_H
+
+#include "FileSystemBlockWriterInterface.h"
+#include "FileSystemBlockAccessExtensions.h"
+
+/* This interface contains an extension scheme that will allow us to 
+ * transparently extend the interface's functionality without losing binary 
+ * compatibility.
+ */
+class INeroFileSystemBlockAccess
+	:public INeroFileSystemBlockWriter
+{
+public:
+
+	// Returns the number of supported extension fields
+	virtual DWORD GetNumSupportedExtensions() = 0;
+	// In combination with the method above, this method can be used to copy a set of extensions
+	// without knowing which ones are actually there. Extensions have to be passed through to
+	// any of the Nero filesystem generators, so it is essential to have some means of copying them
+	virtual INeroFileSystemBlockAccessExtension *GetFileExtensionByNumber(int iNumExt) = 0;
+	// Returns specified extension or NULL if not present
+	virtual INeroFileSystemBlockAccessExtension *GetFileExtension(NeroFSBlockAccessExtensionsType eExtType) = 0;
+
+};
+
+
+#endif // FILESYSTEMBLOCKACCESSINTERFACE_H

+ 95 - 0
Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockReaderInterface.h

@@ -0,0 +1,95 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: FileSystemBlockReaderInterface.h
+|*
+|* PURPOSE: This file contains an abstract interface for reading from block 
+|*          devices. It will provide necessary data about the underlying 
+|*          medium as well as cache data if necessary.
+******************************************************************************/
+#ifndef FILESYSTEMBLOCKREADERINTERFACE_H
+#define FILESYSTEMBLOCKREADERINTERFACE_H
+
+
+#include <windows.h>
+
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+typedef __int64 NeroFSSecNo; // All sector references use this type. LBA adressing is used throughout the interface
+
+typedef enum
+{
+	errOK=0,
+	errEndOfDir,	// Deprecated. Should never be returned, to be treated as errOK
+	errEndOfFile,	// Behaviour see libc read command
+	errReadError,
+	errInvalidFS,
+	errNoDirectory,
+	errNoFile,
+	errNotSupported,
+	errIllegalArgument,
+	errWriteError,
+	errInternalError,
+	errFileLocked,
+	errCopyProtected
+} NeroFSError;
+
+
+typedef enum
+{
+	vtData=0,		// track/partition contains data sectors
+	vtAudio=1,		// track/partition contains audio sectors
+	vtReserved=2	// track/partition hasn't been written yet, 
+					// returned for reserved fragments of DVD+R media (NeroAPI 6.0.0.11+)
+} NeroFSTrackType;
+
+typedef struct 
+{
+	int				PartitionNum;    // The current partition number
+	NeroFSSecNo     PartitionStart;  // The start sector for this Partition
+	NeroFSSecNo		PartitionSize;   // The number of sectors this Partition contains
+	NeroFSTrackType	PartitionType;	 // The type of Partition
+	DWORD			sectorSize;      // Sector size for this Partition
+} NeroFSPartitionInfo;
+
+class INeroFileSystemBlockReader
+{
+public:
+	virtual int					       GetNumPartitions() = 0;
+	virtual const NeroFSPartitionInfo &GetPartitionInfo(int iNumPartition) = 0; 
+
+	// Returns the partition a given sector resides in
+	virtual const NeroFSPartitionInfo &GetPartitionForSector(NeroFSSecNo secNo) = 0;
+
+	// Reading methods. The Buffered varient will use a cache to optimize filesystem access.
+	// It should be used when reading directory structures while the UnBuffered method should be
+	// used when reading file contents
+	// Both methods return error codes as described in NeroFSError
+	// Your read requests may not cross partition boundaries!  
+	virtual NeroFSError ReadSectorsBuffered  (void *pData, NeroFSSecNo startSector, NeroFSSecNo noSectors, NeroFSSecNo &noSectorsRead) = 0;
+	virtual NeroFSError ReadSectorsUnBuffered(void *pData, NeroFSSecNo startSector, NeroFSSecNo noSectors, NeroFSSecNo &noSectorsRead) = 0;
+
+	virtual ~INeroFileSystemBlockReader() {};
+};
+
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+
+#endif // FILESYSTEMBLOCKREADERINTERFACE_H

+ 68 - 0
Burndiscs/Burndiscs/Nero/Include/NeroFileSystemManager/FileSystemBlockWriterInterface.h

@@ -0,0 +1,68 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: FileSystemBlockWriterInterface.h
+|*
+|* PURPOSE: The FileSystem block writer interface is derived from the block 
+|*          reader interface. It defines a path of access to RW filesystems 
+|*          and partitions.
+******************************************************************************/
+#ifndef FILESYSTEMBLOCKWRITERINTERFACE_H
+#define FILESYSTEMBLOCKWRITERINTERFACE_H
+
+#include "FileSystemBlockReaderInterface.h"
+
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+
+// Specifies the block writer type.
+// You can use this information to down-cast the interface to obtain specialized functionality...
+
+// No extensions to the normal blockwrite interface are available so far...	
+enum InterfaceType
+{
+	eBWIUnknown
+};
+
+class INeroFileSystemBlockWriter
+	:public INeroFileSystemBlockReader
+{
+public:
+	// As is the case with the reader interface, the writer interface also provides two methods for sector
+	// access. While WriteSectorsUnBuffered will merely ensure the consistency of the read cache (write thru),
+	// WriteSectorsBuffered will not write anything to the block device immediately but will cache 
+	// a certain amount of sectors before doing so.
+	// The latter increases performance considerably but is prone to data loss in an unstable environment.
+	// Please note that regardless of which method you use, you *must* call FlushSectorCache() if you want
+	// all your data to be at their final physical location because even when writing in UnBuffered mode,
+	// the driver may decide to not write away your data immediately, depending on the underlying 
+	// writing scheme (e.g. packet writing will always try to collect a certain amount of sectors)
+	virtual NeroFSError WriteSectorsBuffered  (const void *pData, NeroFSSecNo startSector, NeroFSSecNo noSectors, NeroFSSecNo &noSectorsWritten) = 0;
+	virtual NeroFSError WriteSectorsUnBuffered(const void *pData, NeroFSSecNo startSector, NeroFSSecNo noSectors, NeroFSSecNo &noSectorsWritten) = 0;
+	// FlushSectorCache will be performed implicitly upon deleting the block writer object
+	virtual void FlushSectorCache() = 0;
+
+	// Runtime type information to be used for downcasting into specialized interfaces...
+	virtual InterfaceType GetBlockWriterType() = 0;
+};
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+
+#endif // FILESYSTEMBLOCKWRITERINTERFACE_H

+ 258 - 0
Burndiscs/Burndiscs/Nero/Include/NeroIsoTrack.h

@@ -0,0 +1,258 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroIsoTrack.h
+|*
+|* PURPOSE: Classes for writing ISO 9660/Joliet track
+|*
+|* NOTE: In contrast to NeroAPI.h, this code is not pure C, but rather C++
+******************************************************************************/
+
+
+#ifndef _NEROISOTRACK_
+#define _NEROISOTRACK_
+
+#include "NeroAPI.h"
+
+#ifndef __cplusplus
+
+#error The Nero ISO Track feature can only be used by C++ code.
+
+#else  /* __cplusplus */
+
+
+#include <windows.h> // the data types used below are those of windows
+
+//
+// The application has to specify the complete layout of the
+// ISO track. The NeroAPI does not care at all where the
+// data for the files comes from. This also means that the
+// application has to provide access to the filename or the
+// data itself when the API needs it.
+//
+
+//
+// Data can be fed into the API directly (i.e. without intermediate
+// files) with CNeroDataCallback:
+//
+class CNeroDataCallback
+{
+public:
+	virtual ~CNeroDataCallback () {}
+
+	virtual DWORD IOCallback(BYTE *pBuffer, DWORD dwLen) = 0;     // same semantic as NERO_IO_CALLBACK in "NeroAPI.h"
+	virtual BOOL EOFCallback () = 0;                              //  "       "       NERO_IO.nioEOFCallback
+	virtual BOOL ErrorCallback () = 0;                            //  "       "       NERO_IO.nioErrorCallback
+};
+
+//
+// The API builds an internal representation of the complete
+// ISO tree and uses a CNeroIsoHandle acquired from the
+// application for each file to access the data later.
+// Usually only one file at once will be left open.
+//
+class CNeroIsoHandle
+{
+public:
+	virtual ~CNeroIsoHandle () {}
+	virtual CNeroIsoHandle * Clone () = 0;                      // make a copy of yourself
+
+	virtual int GetFileName (char *strBuffer, UINT nBufferSize) = 0;  // If the application wants the API to read files, it has to fill
+	                                                                  // the buffer of size nBufferSize with a null-terminated string and return
+	                                                                  // the length of the full name, even if the given buffer was to small.
+	                                                                  // The API will try again with a larger buffer then.
+
+	// return 0 in GetFileName() if you want to provide the data via a CNeroDataCallback:
+	virtual CNeroDataCallback * Open () = 0;                    // return instance ready to read the data associated with this handle or NULL for error;
+	                                                            // this instance will be deleted by NeroAPI;
+	                                                            // usually only one file at once will be left open
+};
+
+//
+// Iterators are used to walk through directories while the API builds
+// its internal copy of the tree. Iterators point to an entry or to NULL,
+// if the last entry was passed, and can only be incremented.
+//
+class CNeroIsoEntry;
+class CNeroIsoIterator
+{
+public:
+	virtual ~CNeroIsoIterator () {}
+
+	virtual CNeroIsoEntry * GetCurrentEntry () = 0;             // get pointer to current entry or NULL if last one passed;
+	                                                            // entry not deleted by API, so the iterator may point to itself
+	                                                            // and implement the required interface (as in the NeroAPI demo),
+	                                                            // or to some permanent entry
+	virtual void Next () = 0;                                   // go to next entry
+};
+
+//
+// An entry (directory or file) is described like this:
+//
+struct CImportInfo;
+class CNeroIsoEntry
+{
+public:
+	virtual ~CNeroIsoEntry () {}
+
+	virtual CNeroIsoIterator * CreateDirectoryIterator() = 0;   // NULL if no directory, otherwise an iterator to step through all child entries;
+	                                                            // iterator will be deleted by NeroAPI
+	
+	virtual const char *       GetName () = 0;                  // the name for this entry; will be copied by API
+	virtual __int64            GetLength () = 0;                // the size of this entry in bytes, or -1 if a directory
+	virtual CNeroIsoHandle *   CreateHandle () = 0;             // creates a handle stored by the API to open a file later, NULL for directory;
+	                                                            // handle will be deleted by NeroAPI when deleting the internal ISO tree
+
+	// The following entries are only needed when e.g. creating your
+	// own Video CD ISO track and not implemented yet.
+	#if 0
+	virtual BOOL               IsMode2 () { return FALSE; }     // TRUE if the application delivers mode 2 data (2336 bytes/block);
+	                                                            // NOTE: the size above are the number of bytes delivered by the application
+	                                                            // NOTE to ahead implementor: in contrast, the ISO entry length always assumes a
+	                                                            // lock size of 2048 and thus GetSize() has to be multiplied by 2048/2336 before using it as CIsoListEntry::size
+	virtual int                GetBlockOffset () { return -1; } // file data is to be written in this block (relative to beginning of ISO track),
+	                                                            // or in a block chosen by NeroAPI if -1
+	#endif
+
+	// Can be used to reference files from previous session
+	virtual DWORD GetDataStartSec() { return 0;}
+	virtual BOOL IsDataFixed() { return FALSE;}
+	virtual BOOL GetEntryTime(struct tm *tm)
+	{
+		return FALSE;	// Unspecified time
+	}
+	// This method was formerly known as GetRockRidgeInfo.
+	// The object returned is a bit different internally now.
+	// Since it is a private structure of NeroAPI this change doesn't matter.
+    virtual CImportInfo *GetImportInfo() const
+    {
+	   // no ImportInfo by default
+	   return NULL;
+	};
+	virtual void GetPriorities(int &iPriority,int &iDirPriority) 
+	{
+		iPriority=0;
+		iDirPriority=0;
+	};
+	// Up from NeroAPI 5.5.9.0
+	virtual CNeroIsoIterator * CreateDirectoryIteratorWrapper() { return NULL;	}
+	// See CreateHandle(). Creates rsc fork handle for HFS filesystems
+	// Will be preferred to reading the resource fork from the file specified by GetName() if !=NULL
+	virtual CNeroIsoHandle *   CreateResourceHandle () { return NULL; };
+
+	virtual const WCHAR* GetUnicodeName() { return 0; } // the name for this entry in unicode format; will be copied by API
+
+	// NeroAPI>=6.0.0.14: Not necessary to implement this. Only used for internal purposes.
+	virtual void *GetInterface(const char *name) { return NULL; }
+private: 
+
+	virtual NERO_UDF_REVISION       GetDesiredUDFRevision()      { return NUR_UDF_INVALID; }
+	virtual NERO_UDF_PARTITION_TYPE GetDesiredUDFPartitionType() { return NUPT_INVALID;    }
+	
+
+	// Reserved for future use
+        virtual int reserved1() { return 0;}
+        virtual int reserved2() { return 0;}
+        virtual int reserved3() { return 0;}
+        virtual int reserved4() { return 0;}
+        virtual int reserved5() { return 0;}
+
+};
+
+
+//
+// An ISO track is a special directory entry:
+//
+struct CNeroIsoTrack : public CNeroIsoEntry
+{
+	friend class CNeroIsoTrackProxy5039;	// Internal compatibility stuff;
+        friend class CNeroIsoTrackProxy55915;   // Internal compatibility stuff;
+
+public:
+	~CNeroIsoTrack () {}
+
+	// essential functions:
+	virtual const char *       GetName () = 0;		            // ISO volume name, copied by API
+	virtual CNeroIsoIterator * CreateDirectoryIterator () = 0;  // iterator for root directory; will be deleted by API
+
+	// these new functions have reasonable defaults:
+	virtual BOOL               UseJoliet () { return TRUE; }    // TRUE if track shall contain Joliet names in addition to ISO
+	virtual BOOL               UseMode2 () { return FALSE; }    // TRUE if track shall be written as mode 2/XA
+
+	// The following 3 functions exist from NeroAPI version 5.5.0.0
+    virtual BOOL               UseRockRidge () { return FALSE; } // RockRidge requires additional informations, so it is off by default
+    virtual BOOL               BurnISO() { return TRUE; } // TRUE if ISO should be created
+    virtual BOOL               BurnUDF() { return FALSE; } // TRUE if UDF should be created
+
+protected:
+	virtual __int64            GetLength () { return -1; }					// we are a directory, ...
+	virtual CNeroIsoHandle *   CreateHandle () { return NULL; }				// ... so we cannot be read
+	virtual CNeroIsoHandle *   CreateResourceHandle () { return NULL; }     // ... so we cannot be read
+
+public:
+	// From NeroAPI version 5.5.1.2
+	// You can set your burn options simply be redefining this function instead of
+	// UseJoliet, UseMode2, UseRockRidge, BurnISO and BurnUDF
+    // See NeroAPI.h for the signification of the NCITEF flags
+    virtual DWORD              BurnOptions() 
+     {
+		return (UseJoliet() ? NCITEF_USE_JOLIET : 0)
+			  |(UseMode2() ? NCITEF_USE_MODE2 : 0)
+			  |(UseRockRidge() ? NCITEF_USE_ROCKRIDGE : 0)
+			  |(BurnISO() ? NCITEF_CREATE_ISO_FS : 0)
+			  |(BurnUDF() ? NCITEF_CREATE_UDF_FS : 0);
+     };
+
+	// Up from NeroAPI 5.5.9.0
+	virtual CNeroIsoIterator *CreateDirectoryIteratorWrapper()
+	{
+		return NULL;
+	}
+
+	virtual BOOL HasWrapper(void)
+	{
+		return FALSE;
+	}
+   
+    // for internal use only. Do not reimplement this method!
+	virtual const void *dummy() const { return NULL; };
+
+	virtual void GetVolumeDescriptor(const char **systemIdentifier, const char **volumeSet
+		, const char **publisher, const char **dataPreparer, const char **application
+		, const char **copyright, const char **abstract, const char **bibliographic)
+	{
+		*systemIdentifier = 0;
+		*volumeSet = 0;
+		*publisher = 0;
+		*dataPreparer = 0;
+		*application = 0;
+		*copyright = 0;
+		*abstract = 0;
+		*bibliographic = 0;
+	}
+
+   
+
+        virtual NERO_UDF_REVISION       GetDesiredUDFRevision()      { return NUR_UDF_INVALID; }
+        virtual NERO_UDF_PARTITION_TYPE GetDesiredUDFPartitionType() { return NUPT_INVALID;    }
+
+        // Reserved for future use
+        virtual int reserved1() { return 0;}
+        virtual int reserved2() { return 0;}
+        virtual int reserved3() { return 0;}
+        virtual int reserved4() { return 0;}
+        virtual int reserved5() { return 0;}
+};
+
+
+#endif /* __cplusplus */
+
+
+#endif /* _NEROISOTRACK_ */

+ 92 - 0
Burndiscs/Burndiscs/Nero/Include/NeroPacketWriting.h

@@ -0,0 +1,92 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroPacketWriting.h
+|*
+|* PURPOSE: This file defines a lowlevel packetwriting/MRW API for NeroAPI
+******************************************************************************/
+#ifndef NEROPACKETWRITING_H
+#define NEROPACKETWRITING_H
+
+#include "NeroAPI.h"
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+#ifdef __cplusplus
+class INeroFileSystemBlockAccess;
+class INeroFileSystemBlockReader;
+extern "C" {
+#else
+typedef void INeroFileSystemBlockAccess;
+typedef void INeroFileSystemBlockReader;
+#endif
+
+
+typedef enum
+{
+	eNoWriting			=0x0000,		/* Use this to instantiate an INeroFileSystemBlockAccess object for read-only access */
+	ePacketWriting		=0x0001,		/* Use this for DVD+RW,DVD-RW,CD-RW media in non-MRW mode */
+	eManagedMRW			=0x0002,		/* Use this for defective managed MRW mode for all media types */
+	eRawMRW				=0x0004,		/* Use this for raw MRW mode (defective management turned off) */
+	eIllegalAccessMode	=0xffffffff
+} AccessMode;
+
+/*
+// Use the following two functions to obtain a block reader/writer to a specified NeroAPI device.
+// Please note that ownership of the aDeviceHandle is *not* transferred to the block writer/reader so you're
+// still responsible to dispose of the device handle after disposing of the writer/reader interface.
+//
+// Please note that only one object created by either NeroCreateBlockWriterInterface or 
+// NeroCreateBlockReaderInterface may exist at a time. Also make sure to delete the object before using
+// the referred drive for another purpose (e.g. importing multisession data, starting a recording- or 
+// digital audio extraction process).
+// Opening a secondary device handle for the drive is *not* sufficient!
+*/
+NEROAPI_API INeroFileSystemBlockAccess* NADLL_ATTR NeroCreateBlockWriterInterface(NERO_DEVICEHANDLE aDeviceHandle,AccessMode eAccessMode);
+NEROAPI_API INeroFileSystemBlockReader* NADLL_ATTR NeroCreateBlockReaderInterface(NERO_DEVICEHANDLE aDeviceHandle,AccessMode eAccessMode);
+
+typedef enum
+{
+	eIAReadOnly				= 0x0000,	// Read-only access to the image/partition
+	eIAInMemoryPatching		= 0x0001,	// Images will be changed in-memory only, without applying the changes to the image/partition
+										// this value was formerly known as eIAReadWrite
+	eIAReadWriteAccess		= 0x0002,	// Read/Write access to the image/partition
+	eIAIllegalAccessMode	= 0xffffffff
+} ImageAccessMode;
+
+/*
+// Create a block access interface for the specified image file
+// Instead of an image file, you may pass a drive letter
+// here to read from a specific device supported by the operating system
+*/
+NEROAPI_API INeroFileSystemBlockAccess* NADLL_ATTR NeroCreateBlockAccessFromImage(const char *szFilename, ImageAccessMode eAccessMode);
+
+/*
+// This function will return a DWORD mask containing values as declared in enum AccessMode.
+// Use ((result&eDesiredMode)!=0) to determine whether a specific mode is supported.
+*/
+NEROAPI_API DWORD					   NADLL_ATTR NeroGetSupportedAccessModesForDevice(NERO_DEVICEHANDLE aDeviceHandle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+
+#endif // NEROPACKETWRITING_H

+ 495 - 0
Burndiscs/Burndiscs/Nero/Include/NeroUserDialog.h

@@ -0,0 +1,495 @@
+/******************************************************************************
+|* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+|* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+|* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+|* PARTICULAR PURPOSE.
+|* 
+|* Copyright 1995-2005 Nero AG. All Rights Reserved.
+|*-----------------------------------------------------------------------------
+|* NeroSDK / NeroAPI
+|*
+|* PROGRAM: NeroUserDialog.h
+|*
+|* PURPOSE: Ask how to proceed by offering the user some choices
+******************************************************************************/
+
+
+#ifndef __NEROUSERDIALOG__
+#define __NEROUSERDIALOG__
+
+#if defined(__BORLANDC__)
+// NEROAPI expects structs to be 8byte aligned
+#pragma pack(push, 8) 
+// tell Borland C++ Builder to treat enums as int
+#pragma option push -b 
+#endif
+
+
+// Take care to use 2^n as values for constants:
+#define AUP_NO_PROBLEM			0			// No problems found
+#define AUP_FIRST_TR_PAUSE		1			// First track must have 2-3 secs pause!
+#define	AUP_PAUSE_SETTINGS		2			// Problem with audio pause settings (tracks > 1)
+#define AUP_INDEX_SETTINGS		4			// Problem with audio index settings
+#define AUP_ISRC_SETTINGS		8			// Problem with ISRC settings
+#define AUP_COPYPROT_SETTINGS	16			// Problem with copyright settings
+#define AUP_NOTRACK_FOUND		32			// Problem because we don´t have any track
+#define AUP_MEGA_FATAL			0xFFFFFFFF	// Megafatal internal problem that can´t be fixed!
+
+typedef enum NeroUserDlgInOutEnum {
+	/* return codes for DLG_MESSAGEBOX: */
+	DLG_RETURN_OK = -8,     /* NeroAPI >= 6.0.0.6: ok */
+	DLG_RETURN_YES = -7,    /* NeroAPI >= 6.0.0.6: yes */
+	DLG_RETURN_RETRY = -6,  /* NeroAPI >= 6.0.0.6: retry */
+	DLG_RETURN_IGNORE = -5,  /* NeroAPI >= 6.0.0.6: ignore */
+	DLG_RETURN_NO = -4,	   /* NeroAPI >= 6.0.0.6: no */
+	DLG_RETURN_CANCEL = -3, /* NeroAPI >= 6.0.0.6: cancel */
+	DLG_RETURN_ABORT = -2, /* NeroAPI >= 6.0.0.6: abort */
+
+	/* NeroAPI >= 6.0.0.6: 
+	 * return this if an enum is not handled by the callback 
+	 */
+	DLG_RETURN_NOT_HANDLED = -1, 
+
+	/* return codes for other dialogs */
+	DLG_RETURN_EXIT = 0,   /* Exit application / stop writing */
+	DLG_RETURN_FALSE = 0,  /* false */
+	DLG_RETURN_TRUE = 1,   /* true */
+
+/*
+"Disconnect is turned off in the system configuration.
+ This may cause serious problems while burning: your CD might
+ be damaged, or the system might hang up."
+*/
+	DLG_DISCONNECT			= 2,
+	DLG_RETURN_ON_RESTART	= 3, /* turn on disconnect and restart windows */
+	DLG_RETURN_RESTART		= 4,    /* Don't change disconnect option and restart windows */
+	DLG_RETURN_CONTINUE		= 5,   /* Continue at your own risk */
+	/* DLG_RETURN_EXIT */
+
+/* same as DLG_DISCONNECT, but restarting has been selected
+   already and must not be canceled, so valid return codes
+   are only DLG_RETURN_ON_RESTART and DLG_RETURN_RESTART */
+	DLG_DISCONNECT_RESTART = 6,
+
+/*
+"Auto Insert Notification is turned on in the system configuration.
+ This may cause serious problems while burning: your CD might be damaged,
+ or the system might hang up.
+
+ Nero is able to burn CDs with Auto Insert Notification turned on if all
+ necessary drivers are installed."
+*/
+	DLG_AUTO_INSERT = 7,			   
+	DLG_RETURN_INSTALL_DRIVER = 8, /* Install IO driver which temporarily disables auto insert. */
+	                           /* Note: this only works if the additional argument for the callback is not NULL,
+							            otherwise it should not be offered to the user. */
+	DLG_RETURN_OFF_RESTART = 9,    /* Change autoinsert and restart Windows */
+	/*
+	as above:
+	DLG_RETURN_EXIT,
+	DLG_RETURN_CONTINUE,
+	*/
+
+/*
+"Please restart Windows now."
+*/
+	DLG_RESTART = 10,
+	/* return code irrelevant */
+
+/*
+"Auto Insert Notification is now OFF. You should restart Windows."
+(displayed after rebooting within program failed and user has to do it manually)
+*/
+	DLG_AUTO_INSERT_RESTART = 11,
+	/* return code irrelevant */
+
+/*
+"Nero detected some modifications of your PC system configuration
+ and needs to modify some settings. Please restart your PC to make 
+ the changes become effective."
+*/
+	DLG_SETTINGS_RESTART = 12,
+	/*
+	DLG_RETURN_RESTART,
+	DLG_RETURN_CONTINUE,
+	*/
+
+/*
+"Sorry, this compilation contains too much data to fit on the CD"
+ with respect to the normal CD capacity. Do you want to try
+ overburn writing at your own risk (this might cause read
+ errors at the end of the CD or might even damage your recorder)?"
+"Note: It is also possible, that SCSI/Atapi errors occur at the end
+ of the simulation or burning. Even in this case there is a certain
+ chance, that the CD is readable."
+
+ NeroAPI >= 6.0.0.27: the data parameter is a pointer to struct DLG_OVERBURN_INFO
+                      defined below.
+*/
+	DLG_OVERBURN = 13,
+	/*
+	DLG_RETURN_TRUE/FALSE
+	*/
+
+
+/*
+The tracks cannot be written as requested. A detailed
+description of the problem is found in the "data" parameter.
+It is a DWORD of with bits set according to the AUP constants above
+*/
+	DLG_AUDIO_PROBLEMS = 14,
+
+	/*
+	DLG_RETURN_TRUE = fix the problems by adapting the track settings
+	DLG_RETURN_FALSE = stop writing
+	*/
+
+
+/*
+This dialog type differs slightly from the other ones:
+it should pop up a message and return immediately while still showing
+the message, so that the API can test for the expected CD in the meantime.
+
+During this time, the NERO_IDLE_CALLBACK will be called to give the
+application a chance to update its display and to test for user abort.
+The API might call call DLG_WAITCD several times to change the text.
+
+The text depends on the "data" argument that is passed to the
+NERO_USER_DIALOG callback. It is the enumeration NERO_WAITCD_TYPE
+specified below.
+*/
+	DLG_WAITCD = 15,
+/*
+It is time to remind the user of inserting the CD: play a jingle, flash the screen, etc.
+Called only once after a certain amount of time of no CD being inserted.
+*/
+	DLG_WAITCD_REMINDER = 16,
+/*
+Close the message box again, we are done.
+*/
+	DLG_WAITCD_DONE = 17,
+/*
+Tell the user that there will be quality loss during the copy and ask if he wants
+to continue anyway
+*/
+	DLG_COPY_QUALITY_LOSS = 18,
+/*
+PROCEED AT YOUR OWN RISK message
+*/
+	DLG_COPY_FULLRISK = 19,
+/*
+Ask the user the path of the file which will be generated by the Image Recorder.
+The "data" argument points on a MAX_PATH or PATH_MAX (depending on your OS) bytes buffer that has to be filled with the image path
+Returning DLG_RETURN_EXIT will stop the burn process
+*/
+	DLG_FILESEL_IMAGE = 20,
+/*
+Tell that there is not enough space on disk to produce this image
+*/
+	DLG_BURNIMAGE_CANCEL = 21,
+
+/*
+Tell the user that the CDRW is not empty
+Starting from NeroAPI 5.5.3.0, the "data" argument contains the device handle from the recorder
+Will be called only if the NBF_DETECT_NON_EMPTY_CDRW flags is given to the NeroBurn function
+Returning DLG_RETURN_EXIT will stop the burn process
+Returning DLG_RETURN_CONTINUE will continue the burn process
+Returning DLG_RETURN_RESTART will ask the user for an other CD
+*/
+	DLG_NON_EMPTY_CDRW = 22,
+
+/*
+NeroAPI 5.5.3.2: tell the user that the compilation cannot be written on that particular 
+recorder and that the user shoud modify his compilation settings or burn the CD on 
+another recorder, that supports the required medium type
+*/
+	DLG_COMP_REC_CONFLICT = 23,
+
+/*
+NeroAPI 5.5.3.2: another type of medium must be used to burn this compilation
+*/
+	DLG_WRONG_MEDIUM = 24,
+/* Implementation of the DLG_ROBO_MOVECD dialog types must behave 
+ * like the DLG_WAITCD type, that is, operate in a non-blocking way.
+ * The data structure passed to this callback is specified as
+ * ROBOMOVEMESSAGE below */
+        DLG_ROBO_MOVECD = 25,
+/* Destroy a MoveCD dialog. (void*)data cast to an int will contain the
+ * id of the MoveCD dialog to be removed */
+        DLG_ROBO_MOVECD_DONE = 26,
+
+/* Show dialog message transmitted by the Robo driver.
+ * Must return one of the constants below.
+ * The data structure passed as the data pointer is specified as
+ * ROBOUSERMESSAGE below.
+ * Return DLG_RETURN_FALSE or DLG_RETURN_TRUE here */
+        DLG_ROBO_USERMESSAGE = 27,
+
+/* Provide informations about which media is expected and which media is
+ * currently present in the recorder.
+   The data pointer passed is a pointer on the NERO_DLG_WAITCD_MEDIA_INFO structure
+   declared in NeroAPI.h. 
+   The value returned is ignored*/
+		DLG_WAITCD_MEDIA_INFO = 28,
+
+/* NeroAPI >= 6.0.0.6: 
+ * Open a custom messagebox dialog. The type and the message of the dialog are described
+ * with a struct NERODLG_MESSAGEBOX which is given as data pointer.
+ * See comments for NERODLG_MESSAGE_TYPE which values to return.
+ */
+	DLG_MESSAGEBOX = 29,
+
+/* NeroAPI >= 6.3.1.9:
+ * "There is not enough free space in the temporary directory.
+ * Please choose another one."
+ * The data parameter is a pointer to struct DLG_TEMPSPACE_INFO defined below.
+ */
+	DLG_TEMPSPACE = 30,
+
+	DLG_MAX
+} NeroUserDlgInOut;
+
+/* NeroAPI >= 6.0.0.6 */
+typedef enum
+{
+	NDIT_INFO = 0, /* an info icon */
+	NDIT_WARNING = 1, /* a warning icon */
+	NDIT_ERROR = 2, /* an error icon */
+	NDIT_QUESTION =3 /* a question icon */
+} NERODLG_ICON_TYPE;
+
+/* NeroAPI >= 6.0.0.6 */
+typedef enum
+{
+	/* An info dialog with only an OK button. The return value is ignored.
+	 */
+	NDMT_OK = 0,
+
+	/* A dialog with a yes and a no button. Return DLG_RETURN_YES for Yes
+	 * and DLG_RETURN_NO for No.
+	 */
+	NDMT_YESNO = 1,
+
+	/* A dialog with a ok and a cancel button. Return DLG_RETURN_OK for OK
+	 * and DLG_RETURN_CANCEL for Cancel.
+	 */
+	NDMT_OKCANCEL = 2,
+	
+	/* A dialog with a retry and a cancel button. Return DLG_RETURN_RETRY 
+	 * for Retry and DLG_RETURN_CANCEL for Cancel.
+	 */
+	NDMT_RETRYCANCEL = 3,
+
+	/* A dialog with a abort, a retry and a ignore button.
+	 * Return DLG_RETURN_IGNORE for Ignore, DLG_RETURN_RETRY for Retry
+	 * and DLG_RETURN_ABORT for Abort.
+	 */
+	NDMT_ABORTRETRYIGNORE = 4,
+
+	/* A dialog with a yes, a no and a cancel button.
+	 * Return DLG_RETURN_YES for Yes, DLG_RETURN_NO for No
+	 * and DLG_RETURN_CANCEL for Cancel.
+	 */
+	NDMT_YESNOCANCEL = 5
+} NERODLG_MESSAGE_TYPE;
+
+/* NeroAPI >= 6.0.0.6 */
+typedef struct
+{
+	NERODLG_MESSAGE_TYPE type; /* the type of the message, see DLG_MESSAGE_TYPE */
+	NERODLG_ICON_TYPE icon; /* the icon for the message, see DLG_ICON_TYPE */
+	NeroUserDlgInOut defaultReturn; /* the default return value */
+	const char* message; /* the message to display */ 
+} NERODLG_MESSAGEBOX;
+
+typedef enum
+{
+   RUMT_ERROR,
+   RUMT_WARNING,
+   RUMT_QUESTION,
+   RUMT_HINT
+} ROBOUSERMESSAGETYPE;
+
+typedef struct
+{
+   ROBOUSERMESSAGETYPE message_type; // The type of message, see constants above */
+   const char *message;
+} ROBOUSERMESSAGE;
+
+typedef enum
+{
+   RMN_INPUT,
+   RMN_RECORDER,
+   RMN_OUTPUT,
+   RMN_PRINTER,
+   RMN_WASTEBIN
+} ROBOMOVENODE;
+
+typedef struct
+{
+   int id; /* In future versions, we may have more than one Robo moving
+	    * at a time. So this ID identifies the movement action
+	    * and will be used to remove it with DLG_ROBO_MOVECD_DONE */
+   ROBOMOVENODE source;
+   ROBOMOVENODE destination;
+} ROBOMOVEMESSAGE;
+
+
+/* NeroAPI >= 6.0.0.27: Additional information when DLG_OVERBURN is called */
+typedef struct
+{
+	DWORD dwTotalBlocksOnCD; /* total blocks to be written to disc */
+	DWORD dwTotalCapacity;   /* free capacity on disc in blocks */
+	DWORD reserved[32];      /* reserved for future usage */
+} DLG_OVERBURN_INFO;
+
+typedef struct
+{
+	const char* pCurrentDir;
+	__int64 i64FreeSpace;	 /* free space on the disc in bytes */
+	__int64 i64SpaceNeeded;  /* space needed in bytes */
+    char* pNewTempDir;       /* a buffer of size iNewTempDirLength where you can
+							  * copy the path to the new temporary directory */
+	int iNewTempDirLength;   /* The size of the pNewTempDirBuffer */
+	DWORD reserved[32];      /* reserved for future usage */
+} DLG_TEMPSPACE_INFO;
+
+
+/*
+// This function gets a requester type and shall return a suitable response to it.
+// Depending on the "type", "data" might contain additional information.
+//
+// Argument passing is in standard C order (on the stack, right to left),
+// aka MS Visual++ __cdecl.
+*/
+
+/* Define __cdecl for non-Microsoft compilers */
+
+#if     ( !defined(_MSC_VER) && !defined(__cdecl) )
+#define __cdecl
+#endif
+
+#define NERO_CALLBACK_ATTR __cdecl
+typedef NeroUserDlgInOut (NERO_CALLBACK_ATTR *NERO_USER_DIALOG) (void *pUserData, NeroUserDlgInOut type, void *data);
+
+/*
+// see below for a description of the enumeration values
+*/
+typedef enum
+{
+    NERO_WAITCD_WRITE,
+    NERO_WAITCD_SIMULATION,
+    NERO_WAITCD_AUTOEJECTLOAD,
+    NERO_WAITCD_REINSERT,
+    NERO_WAITCD_NEXTCD,
+    NERO_WAITCD_ORIGINAL,
+    NERO_WAITCD_WRITEPROTECTED,
+    NERO_WAITCD_NOTENOUGHSPACE,
+    NERO_WAITCD_NEWORIGINAL,
+    NERO_WAITCD_EMPTYCD,
+    NERO_WAITCD_WRITE_EMPTY,
+    NERO_WAITCD_SIMULATION_EMPTY,
+    NERO_WAITCD_WRITEWAVE,
+    NERO_WAITCD_MULTISESSION,
+    NERO_WAITCD_MULTISESSION_SIM,
+    NERO_WAITCD_MULTI_REINSERT,
+	NERO_WAITCD_DISCINFOS_FAILED,
+	NERO_WAITCD_MEDIUM_UNSUPPORTED,
+	NERO_WAITCD_AUTOEJECTLOAD_VER,
+	NERO_WAITCD_REINSERT_VER,
+	NERO_WAITCD_NOFORMAT,
+	NERO_WAITCD_WRONG_MEDIUM,		// NeroAPI>=5.5.5.6
+	NERO_WAITCD_WAITING,			// NeroAPI>=5.5.10.26
+	NERO_WAITCD_EMPTYCDRW,		    // NeroAPI>=6.0.0.20
+	NERO_WAITCD_NOTENOUGHSPACERW,   // NeroAPI>=6.0.0.20
+	NERO_WAITCD_NOTENOUGHSPACE_80MIN,
+    NERO_WAITCD_ISOMULTISESSION_DVDMR9_WARNING,	// NeroAPI>=6.6.0.9
+    NERO_WAITCD_UDFMULTISESSION_DVDMR9_LJR,		// NeroAPI>=6.6.0.9
+    NERO_WAITCD_MAX
+} NERO_WAITCD_TYPE;
+
+
+#endif /* __NEROUSERDIALOG__ */
+
+
+
+#ifdef NERO_WAITCD_TEXTS /* define this in exactly one source file before including NeroUserDialog.h there. */
+
+#include <assert.h>
+
+#ifndef NERO_WAITCD_TEXTS_DEFINED
+#define NERO_WAITCD_TEXTS_DEFINED
+
+
+/* If NeroAPI>=5.5.9.10 is present, it is recommanded to use NeroGetLocalizedWaitCDTexts instead since it 
+   returns a localized string */
+static const char *NeroGetWaitCDTexts (NERO_WAITCD_TYPE type)
+{
+	static struct
+	{
+		NERO_WAITCD_TYPE type;
+		const char *text;
+	} mapping[] =
+	{
+		{ NERO_WAITCD_WRITE,        "Please insert the disc to write to..." },
+		{ NERO_WAITCD_SIMULATION,   "Please insert a disc to use during simulation...\n\n(Nothing will be written on the disc.)" },
+		{ NERO_WAITCD_AUTOEJECTLOAD, 
+									"Please do not remove the disc!\n\nYour recorder requires this eject between simulation and burning. The disc will be reloaded automatically before continuing with burning..." },
+		{ NERO_WAITCD_REINSERT,     "Please do not remove the disc!\n\nYour recorder requires this eject between simulation and burning. Please reinsert the disc..." },
+		{ NERO_WAITCD_NEXTCD,       "Please remove the disc and  insert the next recordable disc to write to... " },
+		{ NERO_WAITCD_ORIGINAL,     "Please insert the original disc." },
+		{ NERO_WAITCD_WRITEPROTECTED, 
+									"This disc is not writable.\n\nPlease insert a writable disc..." },
+		{ NERO_WAITCD_NOTENOUGHSPACE, 
+									"There is not enough space to burn this compilation onto this disc.\n\nPlease insert another disc that provides more space..." },
+		{ NERO_WAITCD_NEWORIGINAL,  "The disc is blank, invalid\nor a multisession disc.\n\nPlease insert original disc ..." },
+		{ NERO_WAITCD_EMPTYCD,      "The disc is not empty.\n\nPlease insert an empty disc." },
+		{ NERO_WAITCD_WRITE_EMPTY,  "Please insert an empty disc to write to..." },
+		{ NERO_WAITCD_SIMULATION_EMPTY, 
+									"Please insert an empty disc to use during simulation...\n\n(Nothing will be written on the disc.)" },
+		{ NERO_WAITCD_WRITEWAVE,    "The disc is blank.\n\nPlease insert original disc..." },
+		{ NERO_WAITCD_MULTISESSION, "Nero is checking for the disc, please wait ...\n\nTo burn this multisession compilation you need the disc, that  contains the previous backup sessions. Please insert this disc if you haven't done it before." },
+		{ NERO_WAITCD_MULTISESSION_SIM, 
+									"To simulate this multisession compilation you need the disc, that contains the previous backup sessions. Please insert this disc. (Nothing will be written on disc)." },
+		{ NERO_WAITCD_MULTI_REINSERT, 
+									"Please do not remove the disc!\n\nYour recorder requires this eject between simulation and burning. Please reinsert the\n same Multisession disc..." },
+		{ NERO_WAITCD_DISCINFOS_FAILED,
+									"Disc analysis failed. The error log\ncontains more information about the reason."},
+		{ NERO_WAITCD_MEDIUM_UNSUPPORTED,
+		"The recorder does not support this type of media!\n\nPlease insert a correct disc to write to..."},
+		{ NERO_WAITCD_AUTOEJECTLOAD_VER, "Please do not remove the disc!\n\nYour recorder requires that the  disc be ejected between burning and verification. The disc will be reloaded automatically when burning is to continue..."	},
+		{ NERO_WAITCD_REINSERT_VER,	"Please do not remove the disc!\n\nYour recorder requires that the disc be ejected between burning and verification. Please reinsert the disc...."	},
+		{ NERO_WAITCD_NOFORMAT,		"The disc is not formatted. Please insert a formatted disc." },
+		{ NERO_WAITCD_WRONG_MEDIUM,	"Sorry, your compilation cannot be written on this kind of disc. Please insert a disc of the correct type or modify the settings of your compilation to make them compatible with the current disc." },
+		{ NERO_WAITCD_WAITING, "--- Accessing disc, please wait ---"},
+		{ NERO_WAITCD_EMPTYCDRW, "The disc is not empty." },
+		{ NERO_WAITCD_NOTENOUGHSPACERW, "There is not enough space to burn the compilation onto this disc."},
+		{ NERO_WAITCD_NOTENOUGHSPACE_80MIN, "There is not enough space to burn the compilation onto this disc.\n\nPlease insert a 80min/700MB media"},
+		{ NERO_WAITCD_ISOMULTISESSION_DVDMR9_WARNING, "Can write multisession or unfinalized DVD-R DL in UDF format only." },
+		{ NERO_WAITCD_UDFMULTISESSION_DVDMR9_LJR, "Can write multisession or unfinalized DVD-R DL on recorders with Layer Jump Recording support only." },
+		{ NERO_WAITCD_MAX,          "unknown NERO_WAITCD_TYPE" }
+	};
+	int i;
+
+	/* 
+	 * Please use NeroGetLocalizedWaitCDTexts instead of NeroGetWaitCDTexts.
+	 * NeroGetLocalizedWaitCDTexts gets the strings from the message file and therefore
+	 * always returns the correct string also if a new NERO_WAITCD_TYPE has been added
+	 * to NeroAPI.
+	 */
+	assert(!"NeroGetWaitCDTexts is deprecated.");
+
+	for (i = 0; mapping[i].type != type && mapping[i].type != NERO_WAITCD_MAX; i++)
+		;
+	assert (mapping[i].type != NERO_WAITCD_MAX);
+	return mapping[i].text;
+}
+#endif
+
+#if defined(__BORLANDC__)
+#pragma pack(pop)
+#pragma option pop 
+#endif
+
+#endif
+

BIN
Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlue.lib


BIN
Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlueBCPPB.lib


BIN
Burndiscs/Burndiscs/Nero/Lib/NeroAPIGlueRT.lib


+ 10 - 0
Burndiscs/Burndiscs/Nero/Lib/Readme.txt

@@ -0,0 +1,10 @@
+NeroAPIGlue.lib: 
+   NeroAPI glue library for use with Visual C++ 7 linked statically with the C runtime library
+
+NeroAPIGlueRT.lib: 
+   NeroAPI glue library for use with Visual C++ 7 linked dynamically with the C runtime library
+
+NeroAPIGlueBCPPB.lib: 
+   NeroAPI glue library for use with Borland C++Builder 6
+   
+NOTE: the libraries compiled with Visual Studio 6 are move to VS6 subfolder.

BIN
Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlue.lib


BIN
Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlueBCPPB.lib


BIN
Burndiscs/Burndiscs/Nero/Lib/VS6/NeroAPIGlueRT.lib


+ 11 - 0
Burndiscs/Burndiscs/Nero/Lib/VS6/Readme.txt

@@ -0,0 +1,11 @@
+NeroAPIGlue.lib: 
+   NeroAPI glue library for use with Visual C++ 6 linked statically with the C runtime library
+
+NeroAPIGlueRT.lib: 
+   NeroAPI glue library for use with Visual C++ 6 linked dynamically with the C runtime library
+
+NeroAPIGlueBCPPB.lib: 
+   NeroAPI glue library for use with Borland C++Builder 6
+   
+NOTE: these libraries are compiled with an older NeroAPI version and does not contain all
+      new features currently introduced.

+ 191 - 0
Burndiscs/Burndiscs/NeroBurndisc.cpp

@@ -0,0 +1,191 @@
+#include "StdAfx.h"
+#include "NeroBurndisc.h"
+
+CDialog* CNeroBurndisc::m_pDailog = NULL;
+IdleCallback CNeroBurndisc::m_pIdelCallback = NULL;
+UserDialog CNeroBurndisc::m_pUserDialog = NULL;
+ProgressCallback CNeroBurndisc::m_pProgressCallback = NULL;
+ProgressCallback CNeroBurndisc::m_pSubTaskProgressCallback = NULL;
+AbortedCallback	CNeroBurndisc::m_pAbortedCallback = NULL;
+AddLogLine CNeroBurndisc::m_pAddLogLine = NULL;
+SetPhaseCallback CNeroBurndisc::m_pSetPhaseCallback = NULL;
+DisableAbortCallback CNeroBurndisc::m_pDisableAbortCallback = NULL;
+SetMajorPhaseCallback CNeroBurndisc::m_pSetMajorPhaseCallback = NULL;
+WriteIOCallback	CNeroBurndisc::m_pWriteIOCallback = NULL;
+ReadIOCallback CNeroBurndisc::m_pReadIOCallback = NULL;
+EOFCallback	CNeroBurndisc::m_pEOFCallback = NULL;
+ErrorCallback CNeroBurndisc::m_pErrorCallback = NULL;
+
+
+CNeroBurndisc::CNeroBurndisc(void)
+:m_pNeroDeviceInfos(NULL)
+,m_bInited(false)
+{
+}
+
+CNeroBurndisc::~CNeroBurndisc(void)
+{
+}
+
+static void NeroError (char *action) /* display Nero error and exit */
+{
+	char *error = NeroGetLastError();
+
+	puts (action);
+	puts (error ? error : "failed");
+
+	NeroFreeMem (error);
+}
+
+/************************************************************************/
+/*  函数:[3/21/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+bool CNeroBurndisc::NeroAPIInit()
+{
+	// 加载Nero的库;
+	if (!NeroAPIGlueConnect(NULL)) {
+		m_strLastError = _T("连接NeroSDK失败!");
+		return false;
+	}
+
+	// 获取Nero库版本信息;
+	WORD ver1, ver2, ver3, ver4;
+	if (!NeroGetAPIVersionEx(&ver1, &ver2, &ver3, &ver4, NULL)) {
+		m_strLastError = _T("获取Nero Version失败!");
+		return false;
+	}
+
+	// 初始化Nero环境(参数固定);
+	strcpy_s(m_pcNeroFilesPath, 128, "NeroFiles");
+	strcpy_s(m_pcVendor, 128, "nero");
+	strcpy_s(m_pcSoftware, 128, "Nero - Burning Rom");
+	strcpy_s(m_pcLanguageFile, 128, "Nero.txt");
+
+	m_NeroSettings.nstNeroFilesPath = m_pcNeroFilesPath;
+	m_NeroSettings.nstVendor = m_pcVendor;
+	m_NeroSettings.nstIdle.ncCallbackFunction = CNeroBurndisc::m_pIdelCallback;
+	m_NeroSettings.nstIdle.ncUserData = CNeroBurndisc::m_pDailog;
+	m_NeroSettings.nstSoftware = m_pcSoftware;
+	m_NeroSettings.nstUserDialog.ncCallbackFunction = CNeroBurndisc::m_pUserDialog;
+	m_NeroSettings.nstUserDialog.ncUserData = CNeroBurndisc::m_pDailog;
+	m_NeroSettings.nstLanguageFile = m_pcLanguageFile;
+
+	NEROAPI_INIT_ERROR Err = NeroInit(&m_NeroSettings, NULL);
+	switch (Err)
+	{
+	case NEROAPI_INIT_OK:
+		m_strLastError = _T("初始化Nero成功!");
+		break;
+	case NEROAPI_INIT_INVALID_ARGS:
+		m_strLastError = _T("NeroInit() : invalid args");
+		break;
+	case NEROAPI_INIT_INVALID_SERIAL_NUM:
+		m_strLastError = _T("NeroInit() : invalid serial number");
+		break;
+	case NEROAPI_INIT_DEMOVERSION_EXPIRED:
+		m_strLastError = _T("NeroInit() : demo version has expired");
+		break;
+	case NEROAPI_INIT_CANNOT_LOCK:
+		m_strLastError = _T("NeroInit() : cannot lock");
+		break;
+	case NEROAPI_INIT_UNSPECIFIED_ERROR:
+		m_strLastError = _T("NeroInit() : unspecified error");
+		break;
+	default:
+		break;
+	}
+
+	return m_bInited = (Err == NEROAPI_INIT_OK ? true : false);
+}
+
+/************************************************************************/
+/*  函数:[3/21/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int CNeroBurndisc::GetAvailableDrives()
+{
+	if (!IsInited())
+		return 0;
+
+	// 清除之前的;
+	if ( m_pNeroDeviceInfos )
+		NeroFreeMem(m_pNeroDeviceInfos);
+
+	// 参数一没什么意义,可以填MEDIA_NONE,MEDIA_CD或MEDIA_DVD_ANY;
+	m_pNeroDeviceInfos = NeroGetAvailableDrivesEx(MEDIA_NONE, NULL);
+
+#ifdef _DEBUG	
+	if (m_pNeroDeviceInfos)
+	{
+		char szDeviceInfo[1024] = {0};
+		for (int i = 0; i < m_pNeroDeviceInfos->nsdisNumDevInfos; i++)
+		{
+			char bufUnderrunProtName[128] = "";
+			char *str;
+			if (m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiCapabilities & NSDI_BUF_UNDERRUN_PROT)
+			{
+				sprintf(bufUnderrunProtName, " (%s)", m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiBufUnderrunProtName);
+
+				if (m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiMandatoryBUPSpeed)
+					sprintf(bufUnderrunProtName + strlen(bufUnderrunProtName)," (recommanded when burning at %dX or faster)",m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiMandatoryBUPSpeed);
+			}
+
+			sprintf_s(szDeviceInfo, "%c. %s: %d (%s), %d, %s%s (%s) (%d KB buffer)\n",
+				// 盘符;
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter ? m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter : '?',
+				// 设备名;
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceName,
+				// 适配号;
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterNo,
+				// 适配名;
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterName,
+				// 设置ID;
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceID,
+				// 容量(是否可刻录);
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiCapabilities&NSDI_ALLOWED ? "" : "(Not allowed) ",
+				bufUnderrunProtName,
+				str = NeroGetTypeNameOfMedia(m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiMediaSupport, ","),
+				m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDriveBufferSize);
+
+			OutputDebugStringA(szDeviceInfo);
+
+			// 列出设备的写速度;
+			for (int i = 0; i < (int)m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiWriteSpeeds.nsiNumSupportedSpeeds; i++)
+			{
+				sprintf_s(szDeviceInfo, "%.1fX (%d KB/s)\n",
+					(float)m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiWriteSpeeds.nsiSupportedSpeedsKBs[i] / m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiWriteSpeeds.nsiBaseSpeedKBs
+					, m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiWriteSpeeds.nsiSupportedSpeedsKBs[i]);
+
+				OutputDebugStringA(szDeviceInfo);
+			}
+
+			NeroFreeMem(str);
+		}
+	}
+#endif
+
+	return m_pNeroDeviceInfos ? m_pNeroDeviceInfos->nsdisNumDevInfos : 0;
+}

+ 76 - 0
Burndiscs/Burndiscs/NeroBurndisc.h

@@ -0,0 +1,76 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/19/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __NERO_SDK__
+#define __NERO_SDK__
+
+#pragma once
+
+#include <vector>
+#include "NeroAPIGlue.h"
+#include "Nero.h"
+
+class CNeroBurndisc
+{	
+public:
+	CNeroBurndisc(void);
+	~CNeroBurndisc(void);
+
+private:
+	// 刻录机设备信息;
+	NERO_SCSI_DEVICE_INFOS*	m_pNeroDeviceInfos;
+	// Nero的刻录设置;
+	NERO_SETTINGS			m_NeroSettings;
+	// 最近的错误日志;
+	CString					m_strLastError;
+
+	char					m_pcLanguageFile[128];
+	char					m_pcSoftware[128];
+	char					m_pcVendor[128];
+	char					m_pcNeroFilesPath[128];
+	char					m_pcDriveName[128];
+	char					m_pcImage[256];
+	bool					m_bAborted;
+	bool					m_bInited;
+
+public:
+	// 回调的对话框;
+	static CDialog*			m_pDailog;
+	static IdleCallback		m_pIdelCallback;
+	static UserDialog		m_pUserDialog;
+	static ProgressCallback m_pProgressCallback;
+	static ProgressCallback m_pSubTaskProgressCallback;
+	static AbortedCallback	m_pAbortedCallback;
+	static AddLogLine		m_pAddLogLine;
+	static SetPhaseCallback m_pSetPhaseCallback;
+	static DisableAbortCallback m_pDisableAbortCallback;
+	static SetMajorPhaseCallback m_pSetMajorPhaseCallback;
+	static WriteIOCallback	m_pWriteIOCallback;
+	static ReadIOCallback	m_pReadIOCallback;
+	static EOFCallback		m_pEOFCallback;
+	static ErrorCallback	m_pErrorCallback;
+	
+public:
+	bool NeroAPIInit();
+	// 获取可用的设备列表;
+	int GetAvailableDrives();	
+	inline bool IsInited() {return m_bInited;}
+	inline CString GetLastError(){return m_strLastError;}
+	inline NERO_SCSI_DEVICE_INFOS* GetDeviceInfs() const {return m_pNeroDeviceInfos;}
+};
+
+#endif

+ 403 - 0
Burndiscs/Burndiscs/NeroDevice.cpp

@@ -0,0 +1,403 @@
+#include "StdAfx.h"
+#include "NeroDevice.h"
+#include "NeroBurndisc.h"
+
+CNeroDevice::CNeroDevice(void)
+	:m_hNeroDevice(NULL)
+	, m_IsOpen(false)
+	, m_pDevInfo(NULL)
+{
+}
+
+CNeroDevice::~CNeroDevice(void)
+{
+	CloseDevice();
+}
+
+bool CNeroDevice::OpenDevice(NERO_SCSI_DEVICE_INFOS* pNeroDeviceInfos, int nDevIndex)
+{
+	if (m_IsOpen && m_hNeroDevice)
+	{
+		m_strLastError = _T("设备已打开!");
+		return true;
+	}
+
+	if (!pNeroDeviceInfos || pNeroDeviceInfos->nsdisNumDevInfos < nDevIndex)
+	{
+		m_strLastError = _T("设备信息对象NULL或个数为0!");
+		return false;
+	}
+
+	m_pDevInfo = &pNeroDeviceInfos->nsdisDevInfos[nDevIndex];
+	m_hNeroDevice = NeroOpenDevice(m_pDevInfo);
+
+	// npProgress will be used during the burn process
+	m_npProgress.npAbortedCallback = CNeroBurndisc::m_pAbortedCallback;
+	m_npProgress.npAddLogLineCallback = CNeroBurndisc::m_pAddLogLine;
+	m_npProgress.npDisableAbortCallback = CNeroBurndisc::m_pDisableAbortCallback;
+	m_npProgress.npProgressCallback = CNeroBurndisc::m_pProgressCallback;
+	m_npProgress.npSetPhaseCallback = CNeroBurndisc::m_pSetPhaseCallback;
+	m_npProgress.npUserData = CNeroBurndisc::m_pDailog;
+	m_npProgress.npSetMajorPhaseCallback = CNeroBurndisc::m_pSetMajorPhaseCallback;
+	m_npProgress.npSubTaskProgressCallback = CNeroBurndisc::m_pSubTaskProgressCallback;
+
+	return m_IsOpen = (m_hNeroDevice ? true : false);
+}
+
+void CNeroDevice::CloseDevice()
+{
+	if (m_hNeroDevice)
+		NeroCloseDevice(m_hNeroDevice);
+
+	m_IsOpen = false;
+	m_pDevInfo = NULL;
+	m_hNeroDevice = NULL;
+}
+
+/************************************************************************/
+/*  函数:获取设备支持的媒体类型[3/21/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+CStringA CNeroDevice::GetMediaSupport()
+{
+	if (!m_IsOpen)
+		return "";
+
+	CStringA strMediaSupport = "";
+
+	char *str = NeroGetTypeNameOfMedia(m_pDevInfo->nsdiMediaSupport, ",");
+	strMediaSupport = str;
+	NeroFreeMem(str);
+
+	return strMediaSupport;
+}
+
+
+/************************************************************************/
+/*  函数:擦除媒体数据[3/21/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] nDevIndex:设备索引;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CNeroDevice::EraseMediaData(bool bEraseEntire /*= false*/)
+{
+	if (!m_IsOpen) return;
+
+	NEROAPI_CDRW_ERASE_MODE mode = bEraseEntire ? NEROAPI_ERASE_ENTIRE : NEROAPI_ERASE_QUICK;
+	int time = NeroGetCDRWErasingTime(m_hNeroDevice, mode);
+
+	if (time == -1)
+		m_strLastError = _T("No CD inserted");
+	else if (time == -2)
+		m_strLastError = _T("This CD recorder doesn't support CDRW");
+	else if (time == -3)
+		m_strLastError = _T("This media is not rewritable");
+
+	int err = NeroEraseCDRW(m_hNeroDevice, mode);
+
+	if (err)
+		m_strLastError = _T("Error erasing the CDRW");
+}
+
+/************************************************************************/
+/*  函数:[3/22/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CNeroDevice::BurnISOorAutoCD(std::string Artist, std::string Title, NERO_ISO_ITEM* pRootItem, bool bImportLastSession /* = false*/)
+{
+	if (!m_IsOpen || pRootItem == NULL)
+		return;
+
+	ASSERT(m_pDevInfo);
+	ASSERT(m_hNeroDevice);
+
+	// 获取媒体信息;
+	NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(m_hNeroDevice, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC);
+	if (pNeroCDInfo == NULL)
+		return;
+
+	// 光盘不可写;
+	if (!pNeroCDInfo->ncdiIsWriteable)
+	{
+		m_strLastError = _T("光盘不可写, 请更换新的光盘!");
+		return;
+	}
+
+	NERO_WRITE_CD writeCD;
+	memset(&writeCD, 0, sizeof(writeCD));
+	writeCD.nwcdpCDStamp = NULL;
+	writeCD.nwcdArtist = Artist.c_str();
+	writeCD.nwcdTitle = Title.c_str();
+	writeCD.nwcdCDExtra = FALSE;
+	writeCD.nwcdNumTracks = 0;
+	writeCD.nwcdMediaType = pNeroCDInfo->ncdiMediaType;
+
+	if (bImportLastSession)
+	{// 追加方式刻录;
+		NERO_IMPORT_DATA_TRACK_INFO nidtInfo;
+		NERO_IMPORT_DATA_TRACK_RESULT nidtResult;
+
+		// Prepare the struct.
+		CStringA csUserMsg = "";
+		memset(&nidtInfo, 0, sizeof(nidtInfo));
+		nidtInfo.nidtiSize = sizeof(nidtInfo);
+		void* pCDStamp = NULL;
+		NERO_ISO_ITEM* pniiItem = NULL;
+		pniiItem = NeroImportDataTrack(m_hNeroDevice, 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 (pRootItem != NULL)
+		{
+			if (MergeIsoTracks(&pRootItem, 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(pRootItem, Title.c_str(), NCITEF_CREATE_ISO_FS | NCITEF_USE_JOLIET);
+
+	// NERO_CD_FORMAT刻录光盘有4种格式;
+	int iRes = NeroBurn(m_hNeroDevice, NERO_ISO_AUDIO_MEDIA, &writeCD, NBF_WRITE | NBF_CLOSE_SESSION, 0, &m_npProgress);
+
+	// 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;
+
+	// 释放媒体资源;
+	NeroFreeMem(pNeroCDInfo);
+
+	switch (iRes)
+	{
+	case NEROAPI_BURN_OK:
+		m_strLastError = _T("BurnCD() : burn successful");
+		break;
+	case NEROAPI_BURN_UNKNOWN_CD_FORMAT:
+		m_strLastError = _T("BurnCD() : unknown CD format");
+		break;
+	case NEROAPI_BURN_INVALID_DRIVE:
+		m_strLastError = _T("BurnCD() : invalid drive");
+		break;
+	case NEROAPI_BURN_FAILED:
+		m_strLastError = _T("BurnCD() : burn failed");
+		break;
+	case NEROAPI_BURN_FUNCTION_NOT_ALLOWED:
+		m_strLastError = _T("BurnCD() : function not allowed");
+		break;
+	case NEROAPI_BURN_DRIVE_NOT_ALLOWED:
+		m_strLastError = _T("BurnCD() : drive not allowed");
+		break;
+	case NEROAPI_BURN_USER_ABORT:
+		m_strLastError = _T("BurnCD() : user aborted");
+		break;
+	case NEROAPI_BURN_BAD_MESSAGE_FILE:
+		m_strLastError = _T("BurnCD() : bad message file");
+		break;
+	default:
+		m_strLastError = _T("BurnCD() : unknown error");
+		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 CNeroDevice::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)
+					{
+						CStringA 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 CNeroDevice::DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem)
+{
+	// First free our own long filename strings, then free the whole tree.
+	FreeOurOwnResources(pniiItem);
+	NeroFreeIsoItemTree(pniiItem);
+}
+
+void CNeroDevice::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 *CNeroDevice::GetAvailableSpeeds(bool IsWriteSpeed /*= true*/)
+{
+	// 获取媒体信息;
+	NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(m_hNeroDevice, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC);
+	if (pNeroCDInfo == NULL)
+		return NULL;
+
+	NERO_SPEED_INFOS *pnsiWrite = NeroGetAvailableSpeeds(m_hNeroDevice, IsWriteSpeed ? ACCESSTYPE_WRITE : ACCESSTYPE_READ, pNeroCDInfo->ncdiMediaType, NULL);
+
+	// 释放媒体资源;
+	NeroFreeMem(pNeroCDInfo);
+
+	return pnsiWrite;
+}

+ 61 - 0
Burndiscs/Burndiscs/NeroDevice.h

@@ -0,0 +1,61 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/21/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __NERO_DEVICE__
+#define __NERO_DEVICE__
+
+#pragma once
+
+#include "NeroAPIGlue.h"
+
+class CNeroDevice
+{
+	// 设备信息对象;
+	NERO_SCSI_DEVICE_INFO*	m_pDevInfo;
+	// 设备句柄;
+	NERO_DEVICEHANDLE		m_hNeroDevice;
+	// 进度条;
+	NERO_PROGRESS			m_npProgress;
+	// 最后的错误信息;
+	CString					m_strLastError;
+	bool m_IsOpen;
+public:
+	CNeroDevice(void);
+	~CNeroDevice(void);
+
+	bool OpenDevice(NERO_SCSI_DEVICE_INFOS* pNeroDeviceInfos, int nDevIndex);
+	void CloseDevice();
+
+	inline bool IsOpen() { return m_IsOpen; }
+	inline NERO_DEVICEHANDLE GetDeviceHandle() const { return m_hNeroDevice; }
+	CStringA GetMediaSupport();
+	bool SetWriteSpeed();
+
+	// 擦除光盘数据;
+	void EraseMediaData(bool bEraseEntire = false);
+
+	BOOL MergeIsoTracks(NERO_ISO_ITEM** ppniiTarget, NERO_ISO_ITEM* pniiToAdd);
+	void DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem);
+	void FreeOurOwnResources(NERO_ISO_ITEM* pniiItem);
+	// 写光盘;
+	void BurnISOorAutoCD(std::string Artist, std::string Title, NERO_ISO_ITEM* pRootItem, bool bImportLastSession = false);
+	void BurnImage();
+	void BurnVideoCDorSuperVideoCD();
+	NERO_SPEED_INFOS *CNeroDevice::GetAvailableSpeeds(bool IsWriteSpeed /*= true*/);
+};
+
+#endif

+ 653 - 0
Burndiscs/Burndiscs/NeroImpl.cpp

@@ -0,0 +1,653 @@
+#include "StdAfx.h"
+#include "NeroImpl.h"
+
+CDialog* CNeroImpl::m_pDailog = NULL;
+IdleCallback CNeroImpl::m_pIdelCallback = NULL;
+UserDialog CNeroImpl::m_pUserDialog = NULL;
+ProgressCallback CNeroImpl::m_pProgressCallback = NULL;
+ProgressCallback CNeroImpl::m_pSubTaskProgressCallback = NULL;
+AbortedCallback	CNeroImpl::m_pAbortedCallback = NULL;
+AddLogLine CNeroImpl::m_pAddLogLine = NULL;
+SetPhaseCallback CNeroImpl::m_pSetPhaseCallback = NULL;
+DisableAbortCallback CNeroImpl::m_pDisableAbortCallback = NULL;
+SetMajorPhaseCallback CNeroImpl::m_pSetMajorPhaseCallback = NULL;
+WriteIOCallback	CNeroImpl::m_pWriteIOCallback = NULL;
+ReadIOCallback CNeroImpl::m_pReadIOCallback = NULL;
+EOFCallback	CNeroImpl::m_pEOFCallback = NULL;
+ErrorCallback CNeroImpl::m_pErrorCallback = NULL;
+
+CNeroImpl::CNeroImpl(void) :m_nRef(0)
+, m_pNeroDeviceInfos(NULL)
+, m_bInited(false)
+{
+}
+
+CNeroImpl::~CNeroImpl(void)
+{
+	if (m_pNeroDeviceInfos)
+	{
+		NeroFreeMem(m_pNeroDeviceInfos);
+	}
+
+	NeroClearErrors();
+	NeroDone();
+	NeroAPIGlueDone();
+}
+
+ULONG CNeroImpl::AddRef()
+{
+	InterlockedIncrement(&m_nRef);
+	return m_nRef;
+}
+
+ULONG CNeroImpl::Release()
+{
+	LONG ulRefCount = InterlockedDecrement(&m_nRef);
+	//如果为0,删除对象;
+	if (m_nRef == 0)
+	{
+		delete this;
+	}
+	return ulRefCount;
+}
+
+HRESULT CNeroImpl::QueryInterface(REFIID riid, __RPC__deref_out void **ppvObject)
+{
+	if (!ppvObject)
+		return E_INVALIDARG;
+
+	*ppvObject = NULL;
+	if (riid == IID_IUnknown || riid == IID_IBurndisc)
+	{
+		*ppvObject = (LPVOID)this;
+		AddRef();
+		return NOERROR;
+	}
+
+	return E_NOINTERFACE;
+}
+
+bool CNeroImpl::Initialize()
+{
+	// 加载Nero的库;
+	if (!NeroAPIGlueConnect(NULL)) {
+		m_strLastError = _T("连接NeroSDK失败!");
+		return false;
+	}
+
+	// 获取Nero库版本信息;
+	WORD ver1, ver2, ver3, ver4;
+	if (!NeroGetAPIVersionEx(&ver1, &ver2, &ver3, &ver4, NULL)) {
+		m_strLastError = _T("获取Nero Version失败!");
+		return false;
+	}
+
+	// 初始化Nero环境(参数固定);
+	strcpy_s(m_pcNeroFilesPath, 128, "NeroFiles");
+	strcpy_s(m_pcVendor, 128, "nero");
+	strcpy_s(m_pcSoftware, 128, "Nero - Burning Rom");
+	strcpy_s(m_pcLanguageFile, 128, "Nero.txt");
+
+	m_NeroSettings.nstNeroFilesPath = m_pcNeroFilesPath;
+	m_NeroSettings.nstVendor = m_pcVendor;
+	m_NeroSettings.nstIdle.ncCallbackFunction = CNeroImpl::m_pIdelCallback;
+	m_NeroSettings.nstIdle.ncUserData = CNeroImpl::m_pDailog;
+	m_NeroSettings.nstSoftware = m_pcSoftware;
+	m_NeroSettings.nstUserDialog.ncCallbackFunction = CNeroImpl::m_pUserDialog;
+	m_NeroSettings.nstUserDialog.ncUserData = CNeroImpl::m_pDailog;
+	m_NeroSettings.nstLanguageFile = m_pcLanguageFile;
+
+	// 初始化;
+	NEROAPI_INIT_ERROR Err = NeroInit(&m_NeroSettings, NULL);
+	switch (Err)
+	{
+	case NEROAPI_INIT_OK:
+		m_strLastError = _T("初始化Nero成功!");
+		break;
+	case NEROAPI_INIT_INVALID_ARGS:
+		m_strLastError = _T("NeroInit() : invalid args");
+		break;
+	case NEROAPI_INIT_INVALID_SERIAL_NUM:
+		m_strLastError = _T("NeroInit() : invalid serial number");
+		break;
+	case NEROAPI_INIT_DEMOVERSION_EXPIRED:
+		m_strLastError = _T("NeroInit() : demo version has expired");
+		break;
+	case NEROAPI_INIT_CANNOT_LOCK:
+		m_strLastError = _T("NeroInit() : cannot lock");
+		break;
+	case NEROAPI_INIT_UNSPECIFIED_ERROR:
+		m_strLastError = _T("NeroInit() : unspecified error");
+		break;
+	default:
+		break;
+	}
+
+	m_NeroProgress.npProgressCallback = m_pProgressCallback;
+	m_NeroProgress.npAbortedCallback = m_pAbortedCallback;
+	m_NeroProgress.npAddLogLineCallback = m_pAddLogLine;
+	m_NeroProgress.npSetPhaseCallback = m_pSetPhaseCallback;
+	m_NeroProgress.npUserData = this;
+	m_NeroProgress.npDisableAbortCallback = m_pDisableAbortCallback;
+	m_NeroProgress.npSetMajorPhaseCallback = m_pSetMajorPhaseCallback;
+	m_NeroProgress.npSubTaskProgressCallback = m_pSubTaskProgressCallback;
+
+	return m_bInited = (Err == NEROAPI_INIT_OK ? true : false);
+}
+
+int CNeroImpl::GetAvailableDrives()
+{
+	if (!m_bInited)
+		return 0;
+
+	// 清除之前的;
+	m_vtDevInfo.clear();
+	if (m_pNeroDeviceInfos)
+		NeroFreeMem(m_pNeroDeviceInfos);
+
+	// 参数一没什么意义,可以填MEDIA_NONE,MEDIA_CD或MEDIA_DVD_ANY;
+	m_pNeroDeviceInfos = NeroGetAvailableDrivesEx(MEDIA_NONE, NULL);
+
+	// 遍历设备;
+	if (m_pNeroDeviceInfos)
+	{
+		char szDevName[MAX_PATH] = { 0 };
+		for (int i = 0; i < m_pNeroDeviceInfos->nsdisNumDevInfos; i++)
+		{
+			if (strcmp(m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterName, "Virtual") != 0)
+			{
+				DeviceInfo devinfo;
+				devinfo.nIndex = i;
+				sprintf_s(szDevName, "%c:\\%s", m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter, m_pNeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceName);
+#ifdef UNICODE
+				int nLen = strlen(szDevName);
+				devinfo.strDevName.append((TCHAR*)(convert("GBK", "UCS-2LE", szDevName, nLen).c_str()), nLen);
+#else
+				devinfo.strDevName = szDevName;
+#endif
+				devinfo.pDevInfo = &m_pNeroDeviceInfos->nsdisDevInfos[i];
+				m_vtDevInfo.push_back(devinfo);
+			}
+		}
+	}
+
+	return m_pNeroDeviceInfos ? m_pNeroDeviceInfos->nsdisNumDevInfos : 0;
+}
+
+void* CNeroImpl::GetDeivceInfo(int nIndex)
+{
+	if (m_vtDevInfo.size() == 0 || nIndex > m_vtDevInfo.size())
+		return NULL;
+
+	return &m_vtDevInfo.at(nIndex);
+}
+
+void* CNeroImpl::GetDeivceInfo(const TCHAR *pszDevName)
+{
+	for (vector<DeviceInfo>::iterator it = m_vtDevInfo.begin(); it != m_vtDevInfo.end(); it++)
+	{
+		if (_tcscmp(pszDevName, it->strDevName.c_str()) == 0)
+		{
+			return &(*it);//或return &m_vtDevInfo.at(it - m_vtDevInfo.begin());
+		}
+	}
+
+	return NULL;
+}
+
+void CNeroImpl::AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles)
+{
+	bool IsNullPath = false;
+	NERO_ISO_ITEM* pHeadItem = NULL;
+	NERO_ISO_ITEM* pNextItem = NULL;
+	if (strFatherNode.size() == 0)
+	{//所有文件,都加到根目录下;
+		IsNullPath = true;
+		pHeadItem = m_BurnItem.FindLastItemInSibling(m_BurnItem.GetHeadItem());
+		if (pHeadItem == NULL)
+			pHeadItem = m_BurnItem.GetVirtualItem();
+	}
+	else
+	{
+		pHeadItem = m_BurnItem.FindPathItem(strFatherNode);
+		if (!pHeadItem)
+		{// 新添根结点;
+			pHeadItem = m_BurnItem.AddPath(strFatherNode);
+			pHeadItem->isDirectory = TRUE;
+		}
+		else
+		{
+			// 找到尾结点;
+			pNextItem = m_BurnItem.FindLastItemInSibling(pHeadItem->subDirFirstItem);
+		}
+	}
+
+	if (pHeadItem)
+	{
+		if (!IsNullPath)
+		{
+			for (vector<TString>::iterator it = vtfiles.begin(); it != vtfiles.end(); it++)
+			{
+				if (pHeadItem->subDirFirstItem)
+					pNextItem = m_BurnItem.AddFile2SiblingItem(pNextItem, *it);
+				else
+					pNextItem = m_BurnItem.AddFile2Path(pHeadItem, *it);
+				if (!pNextItem) break;
+			}
+		}
+		else
+		{
+			for (vector<TString>::iterator it = vtfiles.begin(); it != vtfiles.end(); it++)
+			{
+				pHeadItem = m_BurnItem.AddFile2SiblingItem(pHeadItem, *it);
+				if (!pHeadItem) break;
+			}
+		}
+	}
+}
+
+void CNeroImpl::AddFolder2Disc(IN CONST TString& folder, NERO_ISO_ITEM* pFolderItem)
+{
+	TString path = folder;
+	if (path.size() > 0 && _T('\\') != path[path.size() - 1])
+		path.append(_T("\\"));
+
+	TString file = _T("*");
+	TString s = path + file;
+
+	WIN32_FIND_DATA fileinfo = { 0 };
+	HANDLE handle = FindFirstFile(s.c_str(), &fileinfo);
+
+	NERO_ISO_ITEM* pNextItem = NULL;
+	if (NULL != handle && INVALID_HANDLE_VALUE != handle)
+	{
+		do
+		{
+			// 检查是否超过最大数;
+			//if (checklimit()) break;
+			// '.'和 '..'的系统文件去除;
+			if (_T('.') != fileinfo.cFileName[0])
+			{
+				if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)	// 目录;
+				{
+					pNextItem = m_BurnItem.FindPathInSibling(pFolderItem->subDirFirstItem, TString(fileinfo.cFileName));
+					if (pNextItem == NULL)
+						AddFolder2Disc(path + fileinfo.cFileName, m_BurnItem.AddPath2Path(pFolderItem, fileinfo.cFileName));
+					else
+						AddFolder2Disc(path + fileinfo.cFileName, pNextItem);
+				}
+				else
+				{
+					//if (!checklimit())
+					if (pFolderItem->subDirFirstItem == NULL)
+						pNextItem = m_BurnItem.AddFile2Path(pFolderItem, path + fileinfo.cFileName);
+					else
+					{
+						if (pNextItem == NULL)
+							pNextItem = m_BurnItem.FindLastItemInSibling(pFolderItem->subDirFirstItem);
+						pNextItem = m_BurnItem.AddFile2SiblingItem(pNextItem, path + fileinfo.cFileName);
+					}
+				}
+			}
+		} while (FindNextFile(handle, &fileinfo));
+
+		FindClose(handle);
+	}
+}
+
+void CNeroImpl::AddFolder2Disc(TString strFatherNode, TString strFolder)
+{
+	m_BurnItem.InitVituralItem();
+	NERO_ISO_ITEM* pFolderItem = NULL;
+	if (strFatherNode.size() == 0)
+	{//所有文件,都加到根目录下;
+		strFatherNode = strFolder;
+		if (strFolder[strFolder.size() - 1] == _T('\\'))
+			strFatherNode = strFolder.substr(0, strFolder.size() - 1);
+		strFatherNode = strFatherNode.substr(strFatherNode.find_last_of('\\') + 1);
+	}
+
+	pFolderItem = m_BurnItem.FindPathItem(strFatherNode);
+	if (!pFolderItem)
+	{// 新添根结点;
+		pFolderItem = m_BurnItem.AddPath(strFatherNode);
+	}
+
+	if (pFolderItem == NULL)
+		return;
+
+	pFolderItem->isDirectory = TRUE;
+	AddFolder2Disc(strFolder, pFolderItem);
+}
+
+bool CNeroImpl::BurnMedia(int nIndex, TString strArtist, TString strTitle)
+{
+	// 使用第一个设备来刻录;;
+	NERO_SCSI_DEVICE_INFO* nsdiDevice = &m_pNeroDeviceInfos->nsdisDevInfos[0];
+	// 打开设备;
+	NERO_DEVICEHANDLE hDevice = NeroOpenDevice(nsdiDevice);
+	if (!hDevice)
+	{
+		AfxMessageBox(_T("刻录设备不能打开, 请与系统管理员联系!"), MB_ICONSTOP);
+		return false;
+	}
+
+	// 读取CD或DVD媒体信息;
+	NERO_CD_INFO* pNeroCDInfo = NeroGetCDInfo(hDevice, NGCDI_READ_CD_TEXT | NGCDI_READ_ISRC);
+	if (pNeroCDInfo == NULL)
+	{
+		NeroCloseDevice(hDevice);
+		AfxMessageBox(_T("获取光盘失败, 请与系统管理员联系!"), MB_ICONSTOP);
+		return false;
+	}
+
+	// 光盘不可写;
+	if (!pNeroCDInfo->ncdiIsWriteable)
+	{
+		NeroCloseDevice(hDevice);
+		AfxMessageBox(_T("光盘不可写, 请更换新的光盘!"), MB_ICONSTOP);
+		return false;
+	}
+
+#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;
+
+	if (true)
+	{// 追加方式刻录;
+		NERO_IMPORT_DATA_TRACK_INFO nidtInfo;
+		NERO_IMPORT_DATA_TRACK_RESULT nidtResult;
+
+		// Prepare the struct.
+		//TString csUserMsg		= "";
+		memset(&nidtInfo, 0, sizeof(nidtInfo));
+		nidtInfo.nidtiSize = sizeof(nidtInfo);
+		void* pCDStamp = NULL;
+		NERO_ISO_ITEM* pniiItem = NULL;
+		pniiItem = NeroImportDataTrack(hDevice, 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;
+
+			// 释放资源;
+			if (pCDStamp != NULL)
+				NeroFreeCDStamp(pCDStamp), pCDStamp = NULL;
+
+			NeroFreeMem(pNeroCDInfo);
+
+			NeroCloseDevice(hDevice);
+			m_BurnItem.RemoveAllItem();
+
+			return false;
+			//csUserMsg.Format("There was %s while importing the track!", errors[nidtResult]);
+			//AppendString(csUserMsg);
+		}
+		else if (m_BurnItem.GetHeadItem() != NULL)
+		{
+			if (MergeIsoTracks(&m_BurnItem.GetVirtualItem()->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;
+			}
+		}
+	}
+
+#ifdef UNICODE
+	writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_BurnItem.GetHeadItem(),
+		convert("UCS-2LE", "gb2312", (const char*)strTitle.c_str(), strTitle.size() * sizeof(TCHAR)).c_str(),
+		NCITEF_USE_JOLIET | NCITEF_CREATE_ISO_FS);
+#else
+	writeCD.nwcdIsoTrack = NeroCreateIsoTrackEx(m_BurnItem.GetHeadItem(), strTitle.c_str(), NCITEF_USE_JOLIET | NCITEF_CREATE_ISO_FS);
+#endif
+
+	// 以追回的方式刻录(NBF_CLOSE_SESSION) : 使用MEDIA_DVD_ANY 或 MEDIA_CD时, NERO_CD_FORMAT固定为NERO_ISO_AUDIO_MEDIA;
+	int iRes = NeroBurn(hDevice, NERO_ISO_AUDIO_MEDIA, &writeCD, NBF_WRITE | NBF_CLOSE_SESSION, 0/*Maximum*/, &m_NeroProgress);
+
+	// 释放媒体资源;
+	NeroFreeMem(pNeroCDInfo);
+	// free memory that was allocated for the track
+	if (writeCD.nwcdIsoTrack != NULL)
+		NeroFreeIsoTrack(writeCD.nwcdIsoTrack);
+
+	NeroCloseDevice(hDevice);
+	m_BurnItem.RemoveAllItem();
+
+	// Free the NERO_WRITE_CD struct too
+	if (writeCD.nwcdpCDStamp != NULL)
+		NeroFreeCDStamp(writeCD.nwcdpCDStamp), writeCD.nwcdpCDStamp = NULL;
+
+	char* pszLog = NeroGetErrorLog();
+	switch (iRes)
+	{
+	case NEROAPI_BURN_OK:
+		AfxMessageBox(_T("刻录成功!"), MB_ICONINFORMATION);
+		break;
+	case NEROAPI_BURN_UNKNOWN_CD_FORMAT:
+		AfxMessageBox(_T("刻录失败:无效刻录盘格式!"), MB_ICONSTOP);
+		break;
+	case NEROAPI_BURN_INVALID_DRIVE:
+		AfxMessageBox(_T("刻录失败:驱动器无效!"), MB_ICONSTOP);
+		break;
+	case NEROAPI_BURN_FAILED:
+		AfxMessageBox(_T("刻录失败!"), MB_ICONSTOP);
+		break;
+	case NEROAPI_BURN_FUNCTION_NOT_ALLOWED:
+	case NEROAPI_BURN_DRIVE_NOT_ALLOWED:
+		AfxMessageBox(_T("刻录失败:刻录驱动未安装正确!"), MB_ICONSTOP);
+		break;
+	default:
+		AfxMessageBox(_T("刻录失败:未知错误!"), MB_ICONSTOP);
+		break;
+	}
+
+	NeroFreeMem(pszLog);
+
+	return true;
+}
+
+void CNeroImpl::EraseMedia(int nIndex)
+{
+	ASSERT(nIndex);
+	if (nIndex > m_pNeroDeviceInfos->nsdisNumDevInfos)
+		return;
+	NERO_SCSI_DEVICE_INFO *pDevInfo = &m_pNeroDeviceInfos->nsdisDevInfos[nIndex];
+	NERO_DEVICEHANDLE hNeroDevice = NeroOpenDevice(pDevInfo);
+
+	//NEROAPI_CDRW_ERASE_MODE mode = bEraseEntire ? NEROAPI_ERASE_ENTIRE : NEROAPI_ERASE_QUICK;
+	NEROAPI_CDRW_ERASE_MODE mode = NEROAPI_ERASE_ENTIRE;
+	int time = NeroGetCDRWErasingTime(hNeroDevice, mode);
+
+	if (time == -1)
+		m_strLastError = _T("No CD inserted");
+	else if (time == -2)
+		m_strLastError = _T("This CD recorder doesn't support CDRW");
+	else if (time == -3)
+		m_strLastError = _T("This media is not rewritable");
+
+	int err = NeroEraseCDRW(hNeroDevice, mode);
+
+	if (err)
+		m_strLastError = _T("Error erasing the CDRW");
+
+	NeroCloseDevice(hNeroDevice);
+}
+
+bool CNeroImpl::SetWriteSpeed(ULONG nIndex)
+{
+	return false;
+}
+
+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)
+{
+	CNeroImpl::m_pDailog = (CDialog*)pDailog;
+	CNeroImpl::m_pIdelCallback = pIdleCallback;
+	CNeroImpl::m_pUserDialog = pUserDialog;
+	CNeroImpl::m_pProgressCallback = pProgressCallback;
+	CNeroImpl::m_pSubTaskProgressCallback = pSubTaskProgressCallback;
+	CNeroImpl::m_pAbortedCallback = pAbortedCallback;
+	CNeroImpl::m_pAddLogLine = pAddLogLine;
+	CNeroImpl::m_pSetPhaseCallback = pSetPhaseCallback;
+	CNeroImpl::m_pDisableAbortCallback = pDisableAbortCallback;
+	CNeroImpl::m_pSetMajorPhaseCallback = pSetMajorPhaseCallback;
+	CNeroImpl::m_pWriteIOCallback = pWriteIOCallback;
+	CNeroImpl::m_pReadIOCallback = pReadIOCallback;
+	CNeroImpl::m_pEOFCallback = pEOFCallback;
+	CNeroImpl::m_pErrorCallback = pErrorCallback;
+}
+
+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 CNeroImpl::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)
+					{
+						CStringA 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 CNeroImpl::DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem)
+{
+	// First free our own long filename strings, then free the whole tree.
+	FreeOurOwnResources(pniiItem);
+	NeroFreeIsoItemTree(pniiItem);
+}
+
+void CNeroImpl::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;
+	}
+}

+ 109 - 0
Burndiscs/Burndiscs/NeroImpl.h

@@ -0,0 +1,109 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Jeff];
+/*  日    期:[3/22/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __NERO_IMPL__
+#define __NERO_IMPL__
+
+#pragma once
+
+#include "IBurndisc.h"
+#include "NeroAPIGlue.h"
+#include "Nero.h"
+#include "NeroItem.h"
+
+class CNeroImpl :public IBurndisc
+{
+	volatile LONG m_nRef;
+	// 刻录机设备信息;
+	NERO_SCSI_DEVICE_INFOS*	m_pNeroDeviceInfos;
+	// Nero的刻录设置;
+	NERO_SETTINGS			m_NeroSettings;
+	NERO_PROGRESS			m_NeroProgress;
+	// 最近的错误日志;
+	CString					m_strLastError;
+	// 元素;
+	CDiscItem				m_BurnItem;
+	char					m_pcLanguageFile[128];
+	char					m_pcSoftware[128];
+	char					m_pcVendor[128];
+	char					m_pcNeroFilesPath[128];
+	char					m_pcDriveName[128];
+	char					m_pcImage[256];
+	bool					m_bAborted;
+	bool					m_bInited;
+	std::vector<DeviceInfo>		m_vtDevInfo;
+public:
+	// 回调的对话框;
+	static CDialog*			m_pDailog;
+	static IdleCallback		m_pIdelCallback;
+	static UserDialog		m_pUserDialog;
+	static ProgressCallback m_pProgressCallback;
+	static ProgressCallback m_pSubTaskProgressCallback;
+	static AbortedCallback	m_pAbortedCallback;
+	static AddLogLine		m_pAddLogLine;
+	static SetPhaseCallback m_pSetPhaseCallback;
+	static DisableAbortCallback m_pDisableAbortCallback;
+	static SetMajorPhaseCallback m_pSetMajorPhaseCallback;
+	static WriteIOCallback	m_pWriteIOCallback;
+	static ReadIOCallback	m_pReadIOCallback;
+	static EOFCallback		m_pEOFCallback;
+	static ErrorCallback	m_pErrorCallback;
+public:
+	CNeroImpl(void);
+	~CNeroImpl(void);
+
+	virtual ULONG STDMETHODCALLTYPE AddRef();
+	virtual ULONG STDMETHODCALLTYPE Release();
+	//virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void **ppvObject);
+	virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __RPC__deref_out void **ppvObject);
+
+private:
+	void AddFolder2Disc(IN CONST TString& folder, NERO_ISO_ITEM* pHeadItem);
+	BOOL MergeIsoTracks(NERO_ISO_ITEM** ppniiTarget, NERO_ISO_ITEM* pniiToAdd);
+	void DeleteIsoItemTree(NERO_ISO_ITEM* pniiItem);
+	void FreeOurOwnResources(NERO_ISO_ITEM* pniiItem);
+public:
+	bool Initialize();
+	int GetAvailableDrives();
+	void* GetDeivceInfo(int nIndex);
+	void* GetDeivceInfo(const TCHAR *pszDevName);
+	void AddFiles2Disc(TString strFatherNode, vector<TString> &vtfiles);
+	void AddFolder2Disc(TString strFatherNode, TString strFolder);
+	bool BurnMedia(int nIndex, TString strArtist, TString strTitle);
+	// 擦除设备;
+	void EraseMedia(int nIndex);
+	bool SetWriteSpeed(ULONG nIndex);
+	void 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
+	);
+	void IMAPI2Set(void* pDailog) {};
+};
+
+#endif

+ 914 - 0
Burndiscs/Burndiscs/NeroItem.cpp

@@ -0,0 +1,914 @@
+#include "StdAfx.h"
+#include "NeroItem.h"
+
+
+NERO_ISO_ITEM *CreateNeroIsoItemOfSize(size_t size)
+{
+	return (NERO_ISO_ITEM*)malloc(size);
+}
+
+//#define CreateNeroIsoItem() NeroCreateIsoItemOfSize(sizeof(NERO_ISO_ITEM))//无法分配内存,禁用;
+//#define CreateNeroIsoItem() CreateNeroIsoItemOfSize(sizeof(NERO_ISO_ITEM))
+#define CreateNeroIsoItem() new NERO_ISO_ITEM
+
+CDiscItem::CDiscItem(void)
+{
+	m_pVirtualItem = NULL;
+	InitVituralItem();
+}
+
+CDiscItem::~CDiscItem(void)
+{
+	RemoveAllItem( );
+}
+
+NERO_ISO_ITEM* CDiscItem::InitVituralItem()
+{
+	if ( m_pVirtualItem == NULL )
+	{
+		m_pVirtualItem = CreateNeroIsoItem();
+		ZeroMemory(m_pVirtualItem, sizeof(NERO_ISO_ITEM));
+		m_pVirtualItem->isDirectory = TRUE;
+		m_pVirtualItem->longFileName = _strdup("光盘根级虚元素");
+		m_pVirtualItem->isReference = FALSE;
+		m_pVirtualItem->unicodeFileName = NULL;
+		m_pVirtualItem->nextItem = NULL;
+		m_pVirtualItem->subDirFirstItem = NULL;
+	}
+
+	return m_pVirtualItem;
+}
+
+NERO_ISO_ITEM* CDiscItem::GetHeadItem()
+{
+	if ( m_pVirtualItem == NULL )
+	{
+		m_pVirtualItem = CreateNeroIsoItem();
+		ZeroMemory(m_pVirtualItem, sizeof(NERO_ISO_ITEM));
+		m_pVirtualItem->isDirectory = TRUE;
+		m_pVirtualItem->longFileName = _strdup("光盘根级虚元素");
+		m_pVirtualItem->isReference = FALSE;
+		m_pVirtualItem->unicodeFileName = NULL;
+		m_pVirtualItem->nextItem = NULL;
+		m_pVirtualItem->subDirFirstItem = NULL;
+	}
+
+	return m_pVirtualItem->subDirFirstItem;
+}
+
+/************************************************************************/
+/*  函数:[3/21/2018 Jeff];
+/*  描述:返回光盘要刻录的第一个元素;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::GetVirtualItem()
+{
+	return InitVituralItem();
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:将元素添加到根目录的兄弟链中;
+/*  参数:;
+/*  	[IN] pRootItem:新的根目录兄弟项;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:成功添加返回新项,否则返回NULL;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddSibling2RootItem( IN NERO_ISO_ITEM* pRootItem )
+{
+	if ( m_pVirtualItem == NULL)
+	{
+		if ( InitVituralItem() == NULL )
+			return NULL;
+	}
+
+	if ( pRootItem == NULL )
+		return NULL;
+
+	if ( m_pVirtualItem->subDirFirstItem == NULL )
+	{// 当根元素空时,赋值为第一个值;
+		m_pVirtualItem->subDirFirstItem = pRootItem;
+	}
+	else
+	{
+		NERO_ISO_ITEM* pNextItem = m_pVirtualItem->subDirFirstItem;
+		while( pNextItem->nextItem )
+			pNextItem = pNextItem->nextItem;
+		pNextItem->nextItem = pRootItem;
+	}
+
+	return pRootItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:将元素添加到根目录的兄弟链中;
+/*  参数:;
+/*  	[IN] strRootName:新的根目录兄弟项名称;
+/*  	[IN] bIsDirectory:新的根目录兄弟项类型;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:成功添加返回新项,否则返回NULL;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddSibling2RootItem( IN TString strRootName, IN BOOL bIsDirectory )
+{
+	if ( strRootName.size() )
+		return NULL;
+
+	if ( m_pVirtualItem == NULL)
+	{
+		if ( InitVituralItem() == NULL )
+			return NULL;
+	}
+
+	NERO_ISO_ITEM* pRootItem = CreateNeroIsoItem();
+	ZeroMemory(pRootItem, sizeof(NERO_ISO_ITEM));
+	if ( !bIsDirectory ){// 根元素是文件;
+		TCHAR* name;
+		TCHAR  path[MAX_PATH];
+		GetFullPathName(strRootName.c_str(), MAX_PATH, path, &name);
+#ifdef UNICODE
+		pRootItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)name, _tcslen(name) * sizeof(TCHAR)).c_str());
+		pRootItem->longSourceFilePath = _strdup(convert("UCS-2LE", "GBK", (const char*)path, _tcslen(path) * sizeof(TCHAR)).c_str());
+#else
+		pRootItem->longFileName = _strdup(name);
+		pRootItem->longSourceFilePath = _strdup(path);
+#endif
+		pRootItem->isDirectory = FALSE;		
+		pRootItem->isReference = FALSE;
+		pRootItem->unicodeFileName = NULL;
+		pRootItem->nextItem = NULL;
+		pRootItem->subDirFirstItem = NULL;
+	}else{ // 根元素是目录;
+		pRootItem->isDirectory = TRUE;
+#ifdef UNICODE
+		pRootItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)strRootName.c_str(), strRootName.size() * sizeof(TCHAR)).c_str());
+#else
+		pRootItem->longFileName = _strdup(strRootName.c_str());
+#endif
+		pRootItem->isReference = FALSE;
+		pRootItem->unicodeFileName = NULL;
+		pRootItem->nextItem = NULL;
+		pRootItem->subDirFirstItem = NULL;
+	}
+
+	if ( m_pVirtualItem->subDirFirstItem == NULL )
+	{
+		m_pVirtualItem->subDirFirstItem = pRootItem;
+	}
+	else
+	{
+		NERO_ISO_ITEM* pNextItem = m_pVirtualItem->subDirFirstItem;
+		while( pNextItem->nextItem )
+			pNextItem = pNextItem->nextItem;
+		pNextItem->nextItem = pRootItem;
+	}
+
+	return pRootItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新元素到指定的兄弟项中;
+/*  参数:;
+/*  	[IN] pSiblingItem:作为兄弟链的参考兄弟项;
+/*  	[IN] pNewItem:需要添加兄弟链中的新项;
+/*  	[IN/OUT] :;
+/*  返回:成功添加返回TRUE,否则返回FALSE;
+/*  注意:pSiblingItem不指定具体的类型,如果文件类型(isDirectory==FALSE)或目录类型(isDirectory==TRUE).;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddItem2SiblingItem( IN NERO_ISO_ITEM* pSiblingItem, IN NERO_ISO_ITEM* pNewItem)
+{
+	if ( m_pVirtualItem == NULL || m_pVirtualItem->subDirFirstItem == NULL )
+	{
+		OutputDebugString(_T("\nAddItem2SiblingItem:光盘的根项元素空!\n"));
+		return NULL;
+	}
+
+	if ( pSiblingItem == NULL )
+	{
+		OutputDebugString(_T("\nAddItem2SiblingItem:光盘的兄弟项元素空!\n"));
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNextItem = pSiblingItem;
+	while(pNextItem->nextItem)
+	{
+		pNextItem = pNextItem->nextItem;
+	}
+	pNextItem->nextItem = pNewItem;
+	pNewItem->nextItem = NULL;
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新元素到指定的目录下;
+/*  参数:;
+/*  	[IN] strDiscPath:光盘目录,作为新元素要父目录;
+/*  	[IN] pNewItem:新元素,将插入到strDiscPath目录下;
+/*  	[IN/OUT] :;
+/*  返回:成功添加返回TRUE,否则返回FALS;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddItem2Path( IN TString strDiscPath, IN NERO_ISO_ITEM* pNewItem)
+{
+	if ( m_pVirtualItem == NULL || m_pVirtualItem->subDirFirstItem == NULL)
+	{
+		OutputDebugString(_T("\nAddItem2Path:光盘的根项元素空!\n"));
+		return NULL;
+	}
+
+	if ( strDiscPath.size() )
+	{
+		OutputDebugString(_T("\nAddItem2Path:光盘的兄弟项元素名称空\n"));
+		return NULL;
+	}
+
+	// 首先查找;
+	NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath);
+	if ( pTailPathItem == NULL )
+	{
+		OutputDebugString(_T("\nAddItem2Path:未找到光盘指定路径元素:"));
+		OutputDebugString(strDiscPath.c_str());
+		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;
+	}
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新目录到指定的光盘目录的兄弟链尾中;
+/*  参数:;
+/*  	[IN] strDiscPath:光盘目录,作为新元素兄弟链头路径;
+/*  	[IN] strNewPath:新目录,strDiscPath的兄弟项;
+/*  	[IN/OUT] :;
+/*  返回:成功返回TRUE,否则返回FALSE;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddSiblingPath(IN TString strDiscPath, IN TString strNewPath)
+{
+	// 首先查找;
+	NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath);
+	if ( pTailPathItem == NULL )
+	{
+		OutputDebugString(_T("\nAddPath2Path:未找到光盘指定路径元素:"));
+		OutputDebugString(strDiscPath.c_str());
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = TRUE;
+	pNewItem->isReference = FALSE;
+	pNewItem->unicodeFileName = NULL;
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)strNewPath.c_str(), strNewPath.size() * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(strNewPath.c_str());
+#endif
+	//sprintf_s(pNewItem->fileName, "%s", strNewPath);
+	pNewItem->subDirFirstItem = NULL;
+	pNewItem->nextItem = NULL;
+
+	while( pTailPathItem->nextItem )
+	{
+		pTailPathItem = pTailPathItem->nextItem;
+	}
+
+	pTailPathItem->nextItem = pNewItem;
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新的目录到光盘目录中,若目录不存在,则重新创建目录元素;
+/*  参数:;
+/*  	[IN] strNewPath:新目录,根目录的新兄弟项;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:成功返回TRUE,否则返回FALSE;
+/*  注意:该函数有问题, strNewPath,未进行验证;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddPath(IN TString strNewPath)
+{
+	INT nIndex = 0;
+	nIndex = strNewPath.find_first_of(_T(":\\"));
+	if ( nIndex != TString::npos )
+		strNewPath = strNewPath.substr(nIndex + 2);
+
+	if ( strNewPath[strNewPath.size() - 1] != _T('\\') )
+		strNewPath.append(_T("\\"));
+
+	NERO_ISO_ITEM* pHeadPath = m_pVirtualItem, *pTailPath = pHeadPath->subDirFirstItem;
+	do 
+	{
+		nIndex = strNewPath.find_first_of(_T('\\'));
+		if ( nIndex != TString::npos )
+		{
+			pTailPath = FindPathInSibling(pTailPath, strNewPath.substr(0,nIndex));
+			if (!pTailPath)
+			{
+				break;
+			}
+
+			pHeadPath = pTailPath;
+			pTailPath = pTailPath->subDirFirstItem;
+			strNewPath = strNewPath.substr(nIndex + 1);
+		}		
+	} while (nIndex != -1);
+
+	// 根元素空;
+	if ( m_pVirtualItem->subDirFirstItem == NULL )
+		pHeadPath = m_pVirtualItem;
+
+	while(strNewPath.find_first_of(_T("\\")) != TString::npos) 
+	{
+		nIndex = strNewPath.find_first_of(_T('\\'));
+		if ( nIndex != TString::npos )
+		{
+			pHeadPath = AddPath2Path(pHeadPath, strNewPath.substr(0,nIndex));
+			strNewPath = strNewPath.substr(nIndex + 1);
+		}
+	}
+
+	return pHeadPath;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新目录到指定的光盘目录下;
+/*  参数:;
+/*  	[IN] strDiscPath:光盘目录,作为新元素要父目录;
+/*  	[IN] strNewPath:;
+/*  	[IN/OUT] :新目录,将插入到strDiscPath目录下;
+/*  返回:成功返回TRUE,否则返回FALSE;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddPath2Path(IN TString strDiscPath, IN TString strNewPath)
+{
+	// 首先查找;
+	NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath);
+	if ( pTailPathItem == NULL )
+	{
+		OutputDebugString(_T("\nAddPath2Path:未找到光盘指定路径元素:"));
+		OutputDebugString(strDiscPath.c_str());
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = TRUE;
+	pNewItem->isReference = FALSE;
+	pNewItem->unicodeFileName = NULL;
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)strNewPath.c_str(), strNewPath.size() * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(strNewPath.c_str());
+#endif
+	//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;
+	}
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新目录到指定的光盘目录下;
+/*  参数:;
+/*  	[IN] pPathItem:光盘目录,作为新元素要父目录;
+/*  	[IN] strNewPath:新目录,将插入到strDiscPath目录下;
+/*  	[IN/OUT] :;
+/*  返回:成功返回TRUE,否则返回FALSE;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddPath2Path(IN NERO_ISO_ITEM* pPathItem, IN TString strNewPath )
+{
+	if ( pPathItem == NULL || pPathItem->isDirectory == FALSE )
+	{
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem,sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = TRUE;
+	pNewItem->isReference = FALSE;
+	pNewItem->unicodeFileName = NULL;
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)strNewPath.c_str(), strNewPath.size() * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(strNewPath.c_str());
+#endif
+	//sprintf_s(pNewItem->fileName, "%s", strNewPath);
+	pNewItem->subDirFirstItem = NULL;
+	pNewItem->nextItem = NULL;
+
+	if ( pPathItem->subDirFirstItem == NULL )
+		return pPathItem->subDirFirstItem = pNewItem;
+
+	NERO_ISO_ITEM* pNextItem = pPathItem->subDirFirstItem;
+	while( pNextItem->nextItem)
+	{
+		pNextItem = pNextItem->nextItem;
+	}
+
+	return pNextItem->nextItem = pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:添加新文件到指定的光盘目录下;
+/*  参数:;
+/*  	[IN] strDiscPath:光盘目录,作为新元素的父目录;
+/*  	[IN] strFileName:新文件,将插入到strDiscPath目录下;
+/*  	[IN/OUT] :;
+/*  返回:成功返回TRUE,否则返回FALSE;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddFile2Path(IN TString strDiscPath, IN TString strFileName)
+{
+	// 首先查找;
+	NERO_ISO_ITEM *pTailPathItem = FindPathItem(strDiscPath);
+	if ( pTailPathItem == NULL )
+	{
+		pTailPathItem = AddPath(strDiscPath);
+		if ( pTailPathItem == NULL )
+		{
+			OutputDebugString(_T("\nAddFile2Path:未找到光盘指定路径元素:"));
+			OutputDebugString(strDiscPath.c_str());
+			return NULL;
+		}
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem, sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = FALSE;
+	pNewItem->isReference = FALSE;
+	pNewItem->unicodeFileName = NULL;
+
+	TCHAR* name;
+	TCHAR path[MAX_PATH];
+	GetFullPathName(strFileName.c_str(), MAX_PATH, path, &name);
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)name, _tcslen(name) * sizeof(TCHAR)).c_str());
+	pNewItem->longSourceFilePath = _strdup(convert("UCS-2LE", "GBK", (const char*)path, _tcslen(path) * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(name);
+	pNewItem->longSourceFilePath = _strdup(path);
+#endif
+	//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;
+	}
+
+	return pNewItem;
+}
+
+NERO_ISO_ITEM* CDiscItem::AddFile2Path(IN NERO_ISO_ITEM* pPathItem, IN TString strFileName)
+{
+	if ( pPathItem == NULL && !pPathItem->isDirectory)
+	{
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem, sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = FALSE;
+	pNewItem->isReference = FALSE;
+	pNewItem->unicodeFileName = NULL;
+
+	TCHAR* name;
+	TCHAR path[MAX_PATH];
+	GetFullPathName(strFileName.c_str(), MAX_PATH, path, &name);
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)name, _tcslen(name) * sizeof(TCHAR)).c_str());
+	pNewItem->longSourceFilePath = _strdup(convert("UCS-2LE", "GBK", (const char*)path, _tcslen(path) * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(name);
+	pNewItem->longSourceFilePath = _strdup(path);
+#endif
+	//sprintf_s(pNewItem->fileName,"%s", strFileName);
+	pNewItem->nextItem = NULL;
+	pNewItem->subDirFirstItem = NULL;
+
+	if ( pPathItem->subDirFirstItem )
+	{
+		NERO_ISO_ITEM* pNextItem = pPathItem->subDirFirstItem;
+		while ( pNextItem->nextItem )
+		{
+			pNextItem = pNextItem->nextItem;
+		}
+
+		pNextItem->nextItem = pNewItem;
+	}
+	else
+	{
+		pPathItem->subDirFirstItem = pNewItem;
+	}
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:将文件添加到指定的兄弟项中;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::AddFile2SiblingItem(IN NERO_ISO_ITEM* pSiblingItem, IN TString strFileName)
+{
+	if (pSiblingItem == NULL)
+	{
+		OutputDebugString(_T("\nAddFile2SiblingItem:树兄弟项出错!\n"));
+		return NULL;
+	}
+
+	NERO_ISO_ITEM* pNewItem = CreateNeroIsoItem();
+	ZeroMemory(pNewItem, sizeof(NERO_ISO_ITEM));
+	pNewItem->isDirectory = FALSE;
+	pNewItem->isReference = FALSE;
+
+	TCHAR* name;
+	TCHAR path[MAX_PATH];
+	GetFullPathName(strFileName.c_str(), MAX_PATH, path, &name);
+#ifdef UNICODE
+	pNewItem->longFileName = _strdup(convert("UCS-2LE", "GBK", (const char*)name, _tcslen(name) * sizeof(TCHAR)).c_str());
+	pNewItem->longSourceFilePath = _strdup(convert("UCS-2LE", "GBK", (const char*)path, _tcslen(path) * sizeof(TCHAR)).c_str());
+#else
+	pNewItem->longFileName = _strdup(name);
+	pNewItem->longSourceFilePath = _strdup(path);
+#endif
+
+	pNewItem->nextItem = NULL;
+	pNewItem->subDirFirstItem = NULL;
+
+	NERO_ISO_ITEM* pNextItem = pSiblingItem;
+	while(pNextItem->nextItem)
+	{
+		pNextItem = pNextItem->nextItem;
+	}
+	pNextItem->nextItem = pNewItem;
+
+	return pNewItem;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:查找指定的光盘目录,返回目录元素指针对象;
+/*  参数:;
+/*  	[IN] strDiscPath:要查找的光盘目录,格式如下:"光盘根目录\子目录1\子目录2\子目录3";
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:若存在该光盘目录,则返回该目录元素对象的指针(返回最后一层目录名对应的元素指针),否则返回NULL;;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::FindPathItem( IN TString strDiscPath )
+{
+	if (!strDiscPath.size())
+		return NULL;
+
+	if ( m_pVirtualItem == NULL || m_pVirtualItem->subDirFirstItem == NULL)
+		return NULL;
+
+	INT nIndex = strDiscPath.find_first_of(_T(":\\"));
+	if ( nIndex != TString::npos )
+		strDiscPath = strDiscPath.substr(nIndex + 2);
+
+	if ( strDiscPath[strDiscPath.size()-1] != _T('\\') )
+		strDiscPath.append(_T("\\"));
+
+	NERO_ISO_ITEM* pHeadPath = m_pVirtualItem, *pTailPath = pHeadPath->subDirFirstItem;
+	do 
+	{
+		nIndex = strDiscPath.find_first_of(_T("\\"));
+		if ( nIndex != TString::npos )
+		{
+			pTailPath = FindPathInSibling(pTailPath, strDiscPath.substr(0,nIndex));
+			if (!pTailPath)	{
+				break;
+			}
+
+			pHeadPath = pTailPath;
+			pTailPath = pTailPath->subDirFirstItem;
+			strDiscPath = strDiscPath.substr(nIndex+1);
+		}
+	} while ( strDiscPath.find_first_of(_T("\\")) != -1 );
+
+	return pHeadPath == m_pVirtualItem ? NULL : pHeadPath;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:在指定的兄弟链中(以及兄弟链中的子链),从兄弟链头元素开始查找指定目录名的元素指针;
+/*  参数:;
+/*  	[IN] pSiblingHeadItem:兄弟链的头元素,作为查找时的开始位置;
+/*  	[IN] strDiscPath:要在兄弟链中(以及兄弟链中的子链)查找的目录名(只是单层目录名)。;
+/*  	[IN/OUT] :;
+/*  返回:成功在兄弟链中(以及兄弟链中的子链)查找到该目录名元素,返回该元素对象指针;若未查找到,返回NULL;
+/*  注意:若兄弟链中,存在项,但是另一兄弟项的子链中也存在着同名的项,但却比另一兄弟项先找到,此时就会产生问题;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::FindPathInSibling( IN NERO_ISO_ITEM* pSiblingHeadItem, IN TString& strDiscPath )
+{
+	if ( pSiblingHeadItem == NULL )
+		return NULL;
+
+	BOOL bFind = FALSE;
+	NERO_ISO_ITEM* pNextItem = pSiblingHeadItem;
+	do {
+		if (pNextItem->isDirectory)
+		{
+#ifdef UNICODE
+			if ( convert("UCS-2LE", "GBK", (const char*)strDiscPath.c_str(), strDiscPath.size() * sizeof(TCHAR)).compare(pNextItem->longFileName) == 0 )
+#else
+			if ( strDiscPath.compare(pNextItem->longFileName) == 0 )
+#endif
+			{
+				bFind = TRUE;
+				break;
+			}
+		}
+
+		pNextItem = pNextItem->nextItem;
+	} while ( pNextItem );
+
+	return bFind ? pNextItem : NULL;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:在指定的兄弟链中(以及兄弟链中的子链),从兄弟链头元素开始查找指定目录名的元素指针;
+/*  参数:;
+/*  	[IN] pSiblingHeadItem:兄弟链的头元素,作为查找时的开始位置;
+/*  	[IN] strDiscPath:要在兄弟链中(以及兄弟链中的子链)查找的目录名(只是单层目录名)。;
+/*  	[IN/OUT] :;
+/*  返回:成功在兄弟链中(以及兄弟链中的子链)查找到该目录名元素,返回该元素对象指针;若未查找到,返回NULL;
+/*  注意:先在兄弟链中查找,找不到后再到子链中查找;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::FindPathInSiblingEx( IN NERO_ISO_ITEM* pSiblingHeadItem, IN TString& strDiscPath )
+{
+	if ( pSiblingHeadItem == NULL )
+		return NULL;
+
+	BOOL bFind = FALSE;
+	NERO_ISO_ITEM* pNextItem = pSiblingHeadItem;
+	do {
+		if (pNextItem->isDirectory)
+		{
+#ifdef UNICODE
+			if ( convert("UCS-2LE", "GBK", (const char*)strDiscPath.c_str(), strDiscPath.size() * sizeof(TCHAR)).compare(pNextItem->longFileName) == 0 )
+#else
+			if ( strDiscPath.compare(pNextItem->longFileName) == 0 )
+#endif
+			{
+				bFind = TRUE;
+				break;
+			}
+			else
+			{
+				if ( pNextItem->subDirFirstItem )
+				{
+					NERO_ISO_ITEM *pResultItem = NULL;
+					if ( (pResultItem = FindPathInSibling(pNextItem->subDirFirstItem, strDiscPath)) != NULL )
+					{
+						bFind = TRUE;
+						pNextItem = pResultItem;
+						break;
+					}
+				}
+			}
+		}
+
+		pNextItem = pNextItem->nextItem;
+	} while ( pNextItem );
+
+	return bFind ? pNextItem : NULL;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:返回兄弟链中的倒数第二个元素或者最后一个;
+/*  参数:;
+/*  	[IN] pSiblingHeadItem:兄弟链的头元素;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:返回兄弟链中的倒数第二个元素或者最后一个;
+/*  注意:当兄弟链的只有一个元素时,返回的是本身,也是最后一个;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+NERO_ISO_ITEM* CDiscItem::FindLastItemInSibling( IN NERO_ISO_ITEM* pSiblingHeadItem )
+{
+	if ( pSiblingHeadItem == NULL || pSiblingHeadItem->nextItem == NULL )
+	{
+		return pSiblingHeadItem;
+	}
+
+	NERO_ISO_ITEM* pSiblingTail = pSiblingHeadItem;
+	do
+	{
+		pSiblingTail = pSiblingTail->nextItem; 
+	}while ( pSiblingTail->nextItem );
+
+	return pSiblingTail;
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CDiscItem::DeleteIsoItemTree(NERO_ISO_ITEM *pItem)
+{
+	while(pItem != NULL)
+	{
+		NERO_ISO_ITEM *pNexItem = pItem->nextItem;
+		if ( pItem->isDirectory)
+			DeleteIsoItemTree(pItem->subDirFirstItem);
+
+		if (!pItem->isReference)
+		{// 非引用项;
+			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;
+		}
+		else 
+		{
+			// 引用的必须使用NeroFreeIsoItem释放;
+			NeroFreeIsoItem(pItem);
+		}
+
+		pItem = pNexItem;
+	}
+}
+
+/************************************************************************/
+/*  函数:[3/23/2018 Jeff];
+/*  描述:删除指定根结点的全部元素;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:NeroFreeIsoItemTree函数是用于释放使用CreateNeroIsoItem()创建的对象;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CDiscItem::RemoveAllItem( )
+{
+	DeleteIsoItemTree(m_pVirtualItem);
+	//NeroFreeIsoItemTree(m_pVirtualItem);//如果使用函数CreateNeroIsoItem();来创建,在这里释放;
+	m_pVirtualItem = NULL;
+}

+ 69 - 0
Burndiscs/Burndiscs/NeroItem.h

@@ -0,0 +1,69 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/21/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __DISC_ITEM_20151222__
+#define __DISC_ITEM_20151222__
+
+#pragma once
+
+#include "NeroAPIGlue.h"
+// 注意:
+// 同一个文件的NERO_ISO_ITEM,可以在Nero光盘中不同目录中使用;
+// 在相同的Sibling链中,没有相同的NERO_ISO_IMTE::longFileName/NERO_ISO_ITEM::fileName 或 NERO_ISO_ITEM::longSourceFilePath/NERO_ISO_ITEM::SoucreFilePath;
+
+// NERO_ISO_ITEM形成的树,只能从上往下查找,不能从下往上查找。
+// 如果一个文件目录 或 文件,已存在了,再次刻录该目录或文件时,会自动跳过。
+
+// 注意,Nero SDK 使用的是多字节字符集开发;
+class CDiscItem
+{
+public:
+	CDiscItem(void);
+	~CDiscItem(void);
+
+	// 光盘树根元素;
+	NERO_ISO_ITEM*			m_pVirtualItem;
+public:
+	NERO_ISO_ITEM* InitVituralItem();
+	NERO_ISO_ITEM* GetHeadItem();
+	NERO_ISO_ITEM* GetVirtualItem();	
+	NERO_ISO_ITEM* AddSibling2RootItem( IN NERO_ISO_ITEM* pRootItem );
+	NERO_ISO_ITEM* AddSibling2RootItem( IN TString strRootName, IN BOOL bIsDirectory );
+	NERO_ISO_ITEM* AddItem2SiblingItem( IN NERO_ISO_ITEM* pSiblingItem, IN NERO_ISO_ITEM* pNewItem);
+	NERO_ISO_ITEM* AddItem2Path( IN TString strDiscPath, IN NERO_ISO_ITEM* pNewItem);
+	NERO_ISO_ITEM* AddSiblingPath(IN TString strDiscPath, IN TString strNewPath);
+
+	NERO_ISO_ITEM* AddPath(IN TString strNewPath);
+	NERO_ISO_ITEM* AddPath2Path(IN TString strDiscPath, IN TString strNewPath);
+	NERO_ISO_ITEM* AddPath2Path(IN NERO_ISO_ITEM* pPathItem, IN TString strNewPath );
+	NERO_ISO_ITEM* AddFile2Path(IN TString strDiscPath, IN TString strFileName);
+	NERO_ISO_ITEM* AddFile2Path(IN NERO_ISO_ITEM* pPathItem, IN TString strFileName);
+	NERO_ISO_ITEM* AddFile2SiblingItem(IN NERO_ISO_ITEM* pSiblingItem, IN TString strFileName);
+
+	// 按顺序查找;
+	NERO_ISO_ITEM* FindPathItem( IN TString strDiscPath );
+	NERO_ISO_ITEM* FindPathInSibling( IN NERO_ISO_ITEM* pSiblingHeadItem, IN TString& strDiscPath );
+
+	NERO_ISO_ITEM* FindPathItemEx( IN TString strDiscPath );
+	NERO_ISO_ITEM* FindPathInSiblingEx( IN NERO_ISO_ITEM* pSiblingHeadItem, IN TString& strDiscPath );
+	NERO_ISO_ITEM* FindLastItemInSibling( IN NERO_ISO_ITEM* pSiblingHeadItem );
+	
+	void DeleteIsoItemTree(NERO_ISO_ITEM *pItem);
+	void RemoveAllItem();
+};
+
+#endif

+ 10 - 0
Burndiscs/Burndiscs/NeroMedia.cpp

@@ -0,0 +1,10 @@
+#include "StdAfx.h"
+#include "NeroMedia.h"
+
+CNeroMedia::CNeroMedia(void)
+{
+}
+
+CNeroMedia::~CNeroMedia(void)
+{
+}

+ 34 - 0
Burndiscs/Burndiscs/NeroMedia.h

@@ -0,0 +1,34 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Jeff], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Jeff];
+/*  日    期:[3/21/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Jeff];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __NERO_MEDIA__
+#define __NERO_MEDIA__
+
+#pragma once
+
+#include "NeroAPIGlue.h"
+
+class CNeroMedia
+{
+	// CD或DVD媒体信息;
+	NERO_CD_INFO*	m_pNeroCDInfo;
+public:
+	CNeroMedia(void);
+	~CNeroMedia(void);
+};
+
+#endif

+ 44 - 0
Burndiscs/Burndiscs/ReadMe.txt

@@ -0,0 +1,44 @@
+========================================================================
+    MICROSOFT 基础类库 : Burndiscs 项目概述
+========================================================================
+
+
+应用程序向导已为您创建了此 Burndiscs DLL。此 DLL 不仅演示 Microsoft 基础类的基本使用方法,还可作为您编写 DLL 的起点。
+
+本文件概要介绍组成 Burndiscs DLL 的每个文件的内容。
+
+Burndiscs.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+Burndiscs.h
+    这是 DLL 的主头文件。它声明了 CBurndiscsApp 类。
+
+Burndiscs.cpp
+    这是主 DLL 源文件。它包含 CBurndiscsApp 类。
+
+Burndiscs.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+res\Burndiscs.rc2
+    此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+Burndiscs.def
+    此文件包含在 Microsoft Windows 中运行所必需的 DLL 的有关信息。它定义了 DLL 的名称和说明等参数,而且还从 DLL 导出函数。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 Burndiscs.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 16 - 0
Burndiscs/Burndiscs/Resource.h

@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Burndiscs.rc
+//
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE	2000
+#define _APS_NEXT_CONTROL_VALUE		2000
+#define _APS_NEXT_SYMED_VALUE		2000
+#define _APS_NEXT_COMMAND_VALUE		32771
+#endif
+#endif

BIN
Burndiscs/Burndiscs/dll/libiconv_md.lib


BIN
Burndiscs/Burndiscs/dll/libiconv_mdd.lib


Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно