burncontext.cpp

来自「把doc文档转成pdf后刻录成CD,用VC++开发,用了Nero的SDK和CXI」· C++ 代码 · 共 2,103 行 · 第 1/3 页

CPP
2,103
字号
/******************************************************************************
|* 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-2004 Ahead Software AG. All Rights Reserved.
|*-----------------------------------------------------------------------------
|* NeroSDK / NeroCmd
|*
|* PROGRAM: BurnContext.cpp
|*
|* PURPOSE: Central class for CD operations; implementation file
******************************************************************************/


#include "stdafx.h"
#include "BurnContext.h"

#include "Parameters.h"
#include "Response.h"

CBurnContextProgress::CBurnContextProgress ()
{
	if (m_pNeroProgress != NULL)
	{
		m_pNeroProgress->npAbortedCallback = CBurnContext::AbortedCallback;
		m_pNeroProgress->npAddLogLineCallback = CBurnContext::AddLogLine;
		m_pNeroProgress->npDisableAbortCallback = CBurnContext::DisableAbortCallback;
		m_pNeroProgress->npProgressCallback = CBurnContext::ProgressCallback;
		m_pNeroProgress->npSetMajorPhaseCallback = CBurnContext::SetMajorPhaseCallback;
		m_pNeroProgress->npSetPhaseCallback = CBurnContext::SetPhaseCallback;
		m_pNeroProgress->npSubTaskProgressCallback = NULL;	// Write buffer fill level callback (we don't use this as it is complicated to visualize)
		m_pNeroProgress->npUserData = &CBurnContext::s_NeroSettings;
	}
}


// NERO_SETTINGS is needed when calling NeroInit()

NERO_SETTINGS CBurnContext::s_NeroSettings =
{
	NULL,
	"ahead", "Nero - Burning Rom",
	"Nero.txt",
	{IdleCallback, &s_NeroSettings},
	{UserDialog, &s_NeroSettings}
};

CBurnContext::~CBurnContext ()
{
	// Let the NeroAPI perform the required cleanup

	if (m_bNeroInitialized)
	{
		NeroCloseDevice (m_NeroDeviceHandle);
		NeroFreeMem (m_NeroDeviceInfos);
		NeroFreeMem (m_NeroCDInfo);
		NeroFreeCDStamp (m_pCDStamp);
		NeroClearErrors ();
	}

	// NeroDone needs to be called 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

	if (NeroDone ())
	{
		// If return value is TRUE, some memory leaks were detected.
		// 
	}

	NeroAPIGlueDone();
}


CExitCode CBurnContext::GetAvailableDrives (const PARAMETERS & params)
{
	// Make sure that NeroGetAvailableDrives has not been called before to prevent multiple 
	// allocation of memory for NERO_SCSI_DEVICE_INFOS.

	_ASSERTE (NULL == m_NeroDeviceInfos);

	// NeroGetAvailableDrives returns a list of available WORM and CDROM devices.
	// The memory allocated for NERO_SCSI_DEVICE_INFOS must be freed with NeroFreeMem().
	// This function returns NULL for errors 

	m_NeroDeviceInfos = NeroGetAvailableDrivesEx ((NERO_MEDIA_TYPE) params.GetMediaType (), NULL);

	return (NULL == m_NeroDeviceInfos)? EXITCODE_ERROR_OBTAINING_AVAILABLE_DRIVES: EXITCODE_OK;
}

// Opens the NeroCMD error log

bool CBurnContext::OpenLogFile (LPCSTR psLogFilename)
{
	// We use the CErrorLog class.
	// Open returns true if the error log could be opened.

	return m_ErrorLog.Open (psLogFilename);
}


CExitCode CBurnContext::NeroLoad (void)
{
	// Initialize NeroAPI.

	if (! NeroAPIGlueConnect (NULL))
	{
		return EXITCODE_NEROAPI_DLL_NOT_FOUND;
	}

	// Set the flag.

	m_bNeroInitialized = true;

	return EXITCODE_OK;
}


// This function queries the registry for serial number and initializes
// the NeroAPI.

CExitCode CBurnContext::InitNeroAPI (void)
{
	// Provide the this-pointer for the UserDialog callback

	s_NeroSettings.nstUserDialog.ncCallbackFunction = UserDialog;
	s_NeroSettings.nstUserDialog.ncUserData = this;

	// Do the actual initialization and map the return value
	// into our EXITCODE.

	switch (NeroInit (&s_NeroSettings, NULL))
	{
		case NEROAPI_INIT_OK:
			return EXITCODE_OK;
		
		case NEROAPI_INIT_INVALID_SERIAL_NUM:
			return EXITCODE_BAD_SERIAL_NUMBER;

		case NEROAPI_INIT_DEMOVERSION_EXPIRED:
			return EXITCODE_DEMOVERSION_EXPIRED;
		
		case NEROAPI_INIT_ALREADY_INITIALISED:
		case NEROAPI_INIT_CANNOT_LOCK:
		case NEROAPI_INIT_UNSPECIFIED_ERROR:
		case NEROAPI_INIT_INVALID_ARGS:
		default:
			return EXITCODE_INTERNAL_ERROR;
	}
}


// OpenDevice checks if params.m_psDriveName has a matching
// drive in the list of availabe drives and opens it.

CExitCode CBurnContext::OpenDevice (const PARAMETERS & params)
{
	if (NULL == params.GetDriveName())
	{
		// To open a device we must have its name or drive letter.

		return EXITCODE_MISSING_DRIVENAME;
	}

	// Call the support function that enumerates the drives and finds
	// the requested drive according to the supplied command line
	// parameters.
	//
	int iDriveIndex = LookForADrive (params);

	// If the drive is found (a positive response), try and open it.
	//
	if (iDriveIndex >= 0)
	{
		m_NeroDeviceHandle = NeroOpenDevice (&m_NeroDeviceInfos->nsdisDevInfos[iDriveIndex]);
		if (NULL == m_NeroDeviceHandle) 
		{
			return EXITCODE_ERROR_OPENNING_DRIVE;
		}
	}
	
	// Output a list of available drives and return
	// an error if the requested device could not be found

	if (NULL == m_NeroDeviceHandle)
	{
		printf ("Drive '%s' not found, available are:\n", params.GetDriveName());
		CommandListDrives (params);
		
		return EXITCODE_DRIVE_NOT_FOUND;
	}
	
	return EXITCODE_OK;
}


// This function sets the appropriate burn flags according to the user
// supplied parameters.

DWORD CBurnContext::GetBurnFlags (const PARAMETERS & params)
{
	DWORD dwFlags;

	// Simulation or real mode

	dwFlags = (params.GetUseReal ())? NBF_WRITE : NBF_SIMULATE;

	// DAO (Disc At Once) or TAO (Track At Once)
	// TAO is default

	dwFlags |= (params.GetUseTAO ())? 0 : NBF_DAO;

	// Disable Abort
	// The disable abort callback will be called.

	dwFlags |= (params.GetEnableAbort ())? 0: NBF_DISABLE_ABORT;

	// Perform source speed test first

	dwFlags |= (params.GetUseSpeedTest ())? NBF_SPEED_TEST : 0;

	// Close session after write, not the whole disc

	dwFlags |= (params.GetCloseSession ())? NBF_CLOSE_SESSION: 0;

	// Buffer underrun protection for safer burning

	dwFlags |= (params.GetUseUnderRunProt ()) ? NBF_BUF_UNDERRUN_PROT: 0;

	// Detect non-empty CDRW
	// The DLG_NON_EMPTY_CDRW user callback will be called when trying
	// to burn onto a non empty CDRW

	dwFlags |= (params.GetDetectNonEmptyCDRW ())? NBF_DETECT_NON_EMPTY_CDRW: 0;

	// Enable CD text writing.
	// Will be ignored if the drive does not support this feature

	dwFlags |= (params.GetUseCDText ())? NBF_CD_TEXT: 0;

	// Do not eject CD at the end of the burn process

	dwFlags |= (params.GetDisableEject ())? NBF_DISABLE_EJECT: 0;

	// Verify Filesystem after writing. Works for ISO only
	
	dwFlags |= (params.GetVerify ())? NBF_VERIFY: 0;

	// The speed passed to NeroBurn() is specified in kb/s instead of
	// the usual X.

	dwFlags |= (params.GetSpeedInKbps () >= 0)? NBF_SPEED_IN_KBS: 0;

	// If dvd is burned and a high compatibility mode is specified, this
	// flag is used.

	dwFlags |= (params.GetUseDVDHighCompatibility ())? NBF_DVDP_BURN_30MM_AT_LEAST: 0;

	dwFlags |= (params.GetJapaneseCDText ())? NBF_CD_TEXT_IS_JAPANESE: 0;
	dwFlags |= (params.GetBooktypeDVDROM ())? NBF_BOOKTYPE_DVDROM: 0;
	dwFlags |= (params.GetNoBooktypeChange ())? NBF_NO_BOOKTYPE_CHANGE: 0;

	return dwFlags;
}

// This function is called to exit with a specific error code.

EXITCODE CBurnContext::Exit(CExitCode code)
{
	if (code != EXITCODE_OK)
	{
		LPCSTR psNeroAPIError = code.GetLastError ();

		// If the first char is non-null, the string is non-empty
		// and we should print it. Otherwise, it looks silly.
		// 
		if (psNeroAPIError[0] != 0)
		{
			printf("NeroAPI reports: %s.\n", psNeroAPIError);
		}
	}

	return code;
}

CBurnContext::CBurnContext(PARAMETERS* params)
{
	// A PARAMETERS reference is required for 
	// the UserDialog callback.

	m_params = params;

	m_NeroDeviceHandle = NULL;
	m_NeroDeviceInfos = NULL;
	m_pCDStamp = NULL;
	m_NeroCDInfo = NULL;
	m_bNeroInitialized = false;
	m_bPrintUserInteractionErrorMessage = false;
	
	// Set Ctrl+C handler.
	
	SetConsoleCtrlHandler (CtrlHandler, TRUE);
}

// This function prints error log lines
// that are passed from outside the CBurnContext class

void CBurnContext::PrintLogLine(LPCSTR s)
{
	
	m_ErrorLog.printf ("%s\n", s);
}

// This function rids the string from spaces from the right.
// 
void CBurnContext::TrimStringRight (LPSTR psString)
{
	// Loop from the last string character to the first until the first
	// non-space character is encountered.
	// 
	for (LPSTR p = psString + strlen (psString) - 1;
		psString <= p && *p == ' ';
		p --)
	{
		*p = '\0';
	}
}

// This is a support function that enumerates drives and finds the one
// according to the specified command line parameters.
// 
int CBurnContext::LookForADrive (const PARAMETERS & params)
{
	int i;
	LPSTR psTrimmedDriveName = (LPSTR) _alloca (strlen (params.GetDriveName ()) + 1);
	
	strcpy (psTrimmedDriveName, params.GetDriveName ());
	TrimStringRight (psTrimmedDriveName);

	for (i = 0; i < (int)(m_NeroDeviceInfos->nsdisNumDevInfos); i++) 
	{
		NERO_SCSI_DEVICE_INFO nsdiShort = m_NeroDeviceInfos->nsdisDevInfos[i];
		
		// Check if the full device name has been supplied.
        // stricmp performs a lowercase comparison and returns 0 if the strings are identical.
		
		LPSTR psTrimmedDeviceName = (LPSTR) _alloca (strlen (nsdiShort.nsdiDeviceName) + 1);
		strcpy (psTrimmedDeviceName, nsdiShort.nsdiDeviceName);
		TrimStringRight(psTrimmedDeviceName);

		bool bFoundDeviceName = false;
		if (0 == stricmp (psTrimmedDriveName, psTrimmedDeviceName))
		{
			bFoundDeviceName = true;
		}
		
		// Check if the user supplied drive name is only one character long
		// and see if it matches the drive letter
		
		bool bFoundDriveName = false;
		if (1 == strlen(params.GetDriveName()))
		{
			if (toupper(params.GetDriveName()[0]) == toupper(nsdiShort.nsdiDriveLetter))
			{
				bFoundDriveName = true;
			}
		}
		
		// If either a device name or drive name was found try to open the device
		
		if (bFoundDeviceName || bFoundDriveName)
		{
			// We successfully found the wanted drive. Return the index.

			return i;
		}
	}

	return -1;
}

void CBurnContext::PrintUserInteractionMessage (void)
{
	if (m_bPrintUserInteractionErrorMessage)
	{
		m_bPrintUserInteractionErrorMessage = false;
		printf ("\nERROR: The operation cannot be performed without user interaction!\n");
	}
}


/*            
A. Riazi

PARAMETERS class
*/
// This is a constructor for our PARAMETERS struct which holds
// our command line arguments. All values are here set to some
// reasonable defaults.

PARAMETERS::PARAMETERS ()
{
	// Set this flag to prevent destruction of strings because we
	// don't own them.

	m_FileList.m_bOwnData = false;

	m_bUserInteraction = true;
	m_Command = COMMAND_UNKNOWN;
	m_psDriveName = NULL;
	m_bReal = false;
	m_bTAO = false;
	m_bUnderRunProt = false;
	m_psArtist = NULL;
	m_psTitle = NULL;
	m_iReadSpeed = 0;		// 0 is maximum DAE speed.
	m_iSpeed = -1;			// m_iSpeed is speed in X and m_iSpeedInKbps is
	m_iSpeedInKbps = -1;	// speed in kb/s. -1 means "not set".
	m_bCDExtra = false;
	m_eEraseMode = NEROAPI_ERASE_QUICK;
	m_bEnableAbort = false;
	m_bSpeedTest = false;
	m_bCloseSession = false;
	m_iSessionToImport = -1;
	m_bDetectNonEmptyCDRW = false;
	m_bCDText = false;
	m_bUseRockridge = false;
	m_bCreateIsoFS = false;
	m_bCreateUdfFS = false;
	m_bDVDVideoRealloc = false;
	m_bDVDVideoCmpt = false;
//	m_bImportRockridge = false;			// Not used anymore.
	m_bImportIsoOnly = false;
	m_bImportUDF = false;
	m_bImportVMSSession = false;
	m_bPreferRockridge = false;
	m_bDisableEject = false;
	m_bVerify = false;
	m_bDVD = false;
	m_bDVDHighCompatibility = false;
	m_bAudioSelected = false;
	m_bISOSelected = false;
	
	m_psVolumeName = NULL;
	m_bDontUseJoliet = false;
	m_bMode2 = false;
	m_bVolumeNameSupplied = false;

	m_BurnType = BURNTYPE_UNKNOWN;

	m_psImageFilename = NULL;
	m_psOutputImageFilename = NULL;

	m_iNumTracks = 0;

	m_bProcessedParameterFile = false;

	m_bWriteNeroErrorLog = true;
	m_psErrorLogFilename = NULL;
	m_bNeroLogTimestamp = false;
	m_bForceEraseCDRW = false;

	m_psTempPath = "";

	m_bRecursiveSearch = false;
	m_MediaSet = MEDIA_NONE;

	m_bUseAllSpace = false;
	m_bRelaxJoliet = false;
	m_bJapaneseCDText = false;
	m_bBooktypeDVDROM = false;
	m_bNoBooktypeChange = false;
	m_bDisableEjectAfterErase = false;
	m_bForceEjectAfterErase = false;
	m_psImageInfoFilename = NULL;
	m_psSystemIdentifier = NULL;
	m_psVolumeSet = NULL;
	m_psPublisher = NULL;
	m_psDataPreparer = NULL;
	m_psApplication = NULL;
	m_psCopyright = NULL;
	m_psAbstract = NULL;
	m_psBibliographic = NULL;

	m_bImportSession = false;

	m_bBackup = false;

	m_VideoResolution = NERO_VIDEO_RESOLUTION_PAL;

	m_bEstimateFSOverhead = false;
	m_bEstimateData = false;
	m_bEstimateExactSize = false;
}


int PARAMETERS::GetFileListSize() const
{
	return m_FileList.GetSize();
}

const CSimpleStringArray& PARAMETERS::GetFileList() const
{
	return m_FileList;
}

CSimpleStringArray& PARAMETERS::GetFileList()
{
	return m_FileList;
}

LPCSTR PARAMETERS::GetErrorLogName() const
{
	return m_psErrorLogFilename;
}

COMMAND_LINE_ERRORS PARAMETERS::SetErrorLogName(int& argc, char**& argv)
{
	argc--;
	argv++;

	if (argc <= 0)
	{
		return CLE_MISSING_ERROR_LOG_PARAMETER;
	}

	m_psErrorLogFilename = *argv;
	return CLE_NO_ERROR;
}

COMMAND_LINE_ERRORS PARAMETERS::SetWriteErrorLog()
{
	m_bWriteNeroErrorLog = false;
	return CLE_NO_ERROR;
}

bool PARAMETERS::GetWriteErrorLog() const
{
	return m_bWriteNeroErrorLog;
}

COMMAND_LINE_ERRORS PARAMETERS::SetProcessedParameterFile()
{
	if (COMMAND_UNKNOWN != m_Command)
	{
		return CLE_MULTIPLE_COMMANDS_SPECIFIED;
	}

	m_bProcessedParameterFile = true;
	return CLE_NO_ERROR;
}

bool PARAMETERS::GetProcessedParameterFile()
{
	return m_bProcessedParameterFile;
}

const TRACK PARAMETERS::GetTrack(int iTrack) const
{
  return m_Tracks[iTrack];
}

const bool PARAMETERS::StillTrackSpaceLeft() const
{
	return m_iNumTracks < sizeof (m_Tracks)/sizeof (m_Tracks[0]);
}

TRACK& PARAMETERS::GetTrack (int iTrack)
{
	return m_Tracks[iTrack];
}

const int PARAMETERS::GetTrackNumber(int iTrack) const
{
	return m_Tracks[iTrack].m_iTrack;
}

const LPCSTR PARAMETERS::GetTrackFileName (int iTrack) const
{
	return m_Tracks[iTrack].m_psFilename;
}

const NERO_TRACKMODE_TYPE PARAMETERS::GetTrackMode(int iTrack) const
{
	return m_Tracks[iTrack].m_Mode;
}

COMMAND_LINE_ERRORS PARAMETERS::SetTrackFileName(int iTrack, const char *psName)
{
	m_Tracks[iTrack].m_psFilename = psName;
	return CLE_NO_ERROR;
}

const int PARAMETERS::GetNumberOfTracks() const
{
	return m_iNumTracks;
}

COMMAND_LINE_ERRORS PARAMETERS::SetTrackMode(int iTrack, NERO_TRACKMODE_TYPE eType)
{
	m_Tracks[iTrack].m_Mode = eType;
	return CLE_NO_ERROR;
}

COMMAND_LINE_ERRORS PARAMETERS::IncrementNumberOfTracks()
{
	m_iNumTracks++;
	return CLE_NO_ERROR;
}

COMMAND_LINE_ERRORS PARAMETERS::SetTrackNumber(int iTrack, int iNumber)
{
	m_Tracks[iTrack].m_iTrack = iNumber;
	return CLE_NO_ERROR;
}

const NEROAPI_CDRW_ERASE_MODE PARAMETERS::GetEraseMode() const
{
	return m_eEraseMode;
}

COMMAND_LINE_ERRORS PARAMETERS::SetEraseMode(NEROAPI_CDRW_ERASE_MODE eMode)
{
	if (GetEraseMode() == eMode)
	{
		return CLE_MULTIPLE_COMMANDS_SPECIFIED;
	}

	m_eEraseMode = eMode;
	return CLE_NO_ERROR;
}

COMMAND_LINE_ERRORS PARAMETERS::SetImageFileName(const char *psName)
{
	m_psImageFilename = psName;
	return CLE_NO_ERROR;
}

const LPCSTR PARAMETERS::GetImageFileName() const
{
	return m_psImageFilename;
}

COMMAND_LINE_ERRORS PARAMETERS::SetOutputImageFileName(int& argc, char**& argv)
{
	argc--;
	argv++;

	if (argc <= 0)
	{
		return CLE_MISSING_OUTPUT_IMAGE_FILENAME_PARAMETER;
	}
		
	m_psOutputImageFilename = *argv;
	return CLE_NO_ERROR;
}

const LPCSTR PARAMETERS::GetOutputImageFileName() const
{
	return m_psOutputImageFilename;
}

COMMAND_LINE_ERRORS PARAMETERS::SetBurnType(BURNTYPE Type)
{
	// The Burn type cannot be set twice
	// BURNTYPE_ISOAUDIO is an exception to this rule.
	// However, settings for ISO/Audio and mixed more are handled
	// in SetAudioSelected and SetISOSelected directly.
	// So we do not have to worry about that here.
	// Another exception is BURNTYPE_FREESTYLE, where every
	// track can be written in a different mode.
	// So it is legal to provide that type more than once.

	if (BURNTYPE_UNKNOWN != GetBurnType())
	{
		if (BURNTYPE_FREESTYLE != GetBurnType())
		{
			// A burn type other than freestyle has been set already. 

			return CLE_BURN_TYPE_ALREADY_SPECIFIED;
		}
		else
		{
			// The burn type set before is freestyle.
			// If the new type is not BURNTYPE_FREESTYLE
			// we need to return an error.

			if (BURNTYPE_FREESTYLE != Type)
			{
				// Illegal combination of types

				return CLE_BURN_TYPE_ALREADY_SPECIFIED;
			}
		}
	}

	// Burn type has not been specified yet, so just set it

	m_BurnType = Type;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?