www.pudn.com > NEROSDK5582.ZIP > BurnContext.cpp
/******************************************************************************
|* 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-2002 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"
// Set pointers to callback functions
NERO_PROGRESS CBurnContext::s_NeroProgress =
{
ProgressCallback,
AbortedCallback,
AddLogLine,
SetPhaseCallback,
&s_NeroSettings,
DisableAbortCallback,
};
// 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 ()
{
m_NeroDeviceHandle = NULL;
m_NeroDeviceInfos = NULL;
m_pCDStamp = NULL;
m_NeroCDInfo = NULL;
m_bNeroInitialized = false;
m_pNeroLastError = NULL;
// Set Ctrl+C handler.
SetConsoleCtrlHandler (CtrlHandler, TRUE);
}
CBurnContext::~CBurnContext ()
{
// Let the NeroAPI perform the required cleanup
if (true == m_bNeroInitialized)
{
NeroCloseDevice (m_NeroDeviceHandle);
NeroFreeMem (m_NeroDeviceInfos);
NeroFreeMem (m_NeroCDInfo);
NeroFreeCDStamp (m_pCDStamp);
NeroClearErrors ();
}
// Free memory allocated during retrieval of
// NeroAPI's last error. No checking against NULL
// required, this will be done by free().
free(m_pNeroLastError);
// 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
NeroDone ();
}
EXITCODE CBurnContext::GetAvailableDrives (void)
{
// 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 (MEDIA_CD,NULL);
if (NULL == m_NeroDeviceInfos)
{
GetLastErrorLogLine();
return EXITCODE_ERROR_OBTAINING_AVAILABLE_DRIVES;
}
else
{
return 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);
}
EXITCODE CBurnContext::NeroLoad (void)
{
// Finally, initialize NeroAPI.
if (!TRUE == 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.
EXITCODE 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_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.
EXITCODE 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;
}
// Enumerate drives and find the requested drive among them.
for (int 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.
bool bFoundDeviceName = false;
if (0 == stricmp (params.GetDriveName(), nsdiShort.nsdiDeviceName))
{
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)
{
m_NeroDeviceHandle = NeroOpenDevice (&m_NeroDeviceInfos->nsdisDevInfos[i]);
if (NULL == m_NeroDeviceHandle)
{
GetLastErrorLogLine();
return EXITCODE_ERROR_OPENNING_DRIVE;
}
// We successfully retrieved a handle. Break the for-loop.
break;
}
}
// 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
if (true == params.GetUseReal())
{
dwFlags = NBF_WRITE;
}
else
{
dwFlags = NBF_SIMULATE;
}
// DAO (Disc At Once) or TAO (Track At Once)
// TAO is default
if (false == params.GetUseTAO())
{
dwFlags |= NBF_DAO;
}
// Disable Abort
// The disable abort callback will be called.
if (false == params.GetEnableAbort())
{
dwFlags |= NBF_DISABLE_ABORT;
}
// Perform source speed test first
if (true == params.GetUseSpeedTest())
{
dwFlags |= NBF_SPEED_TEST;
}
// Close session after write, not the whole disc
if (true == params.GetCloseSession())
{
dwFlags |= NBF_CLOSE_SESSION;
}
// Buffer underrun protection for safer burning
if (true == params.GetUseUnderRunProt())
{
dwFlags |= NBF_BUF_UNDERRUN_PROT;
}
// Detect non-empty CDRW
// The DLG_NON_EMPTY_CDRW user callback will be called when trying
// to burn onto a non empty CDRW
if (true == params.GetDetectNonEmptyCDRW())
{
dwFlags |= NBF_DETECT_NON_EMPTY_CDRW;
}
// Enable CD text writing.
// Will be ignored if the drive does not support this feature
if (true == params.GetUseCDText())
{
dwFlags |= NBF_CD_TEXT;
}
// Do not eject CD at the end of the burn process
if (true == params.GetDisableEject())
{
dwFlags |= NBF_DISABLE_EJECT;
}
// Verify Filesystem after writing. Works for ISO only
if (true == params.GetVerify())
{
dwFlags |= NBF_VERIFY;
}
return dwFlags;
}
// Copy the first occuring NeroAPI error to a member
// and keep it until application exits.
void CBurnContext::GetLastErrorLogLine()
{
// Get a pointer to the last error string
char* pErr = NeroGetLastError();
// Only proceed if there was an error
// and no previous error has occured.
if (NULL != pErr && NULL == m_pNeroLastError)
{
// Allocate some memory for the error string
// and copy the error message to the CBurnContext class
// so we can let NeroAPI free the string immediately.
// The allocated memory in CBurnContext will
// be freed during destruction.
size_t iErrSize = strlen(pErr);
// strlen does not count the terminal NULL, so we
// need to allocate iErrSize + 1 bytes.
m_pNeroLastError = (char*) malloc(iErrSize + 1);
strcpy(m_pNeroLastError, pErr);
NeroFreeMem(pErr);
}
}
// This function is called to exit with a specific error code.
EXITCODE CBurnContext::Exit(EXITCODE code)
{
if (code != EXITCODE_OK)
{
printf ("\n%s\n", GetTextualExitCode (code));
if (NULL != m_pNeroLastError)
{
printf("NeroAPI reports: %s.\n", m_pNeroLastError);
}
}
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_pNeroLastError = NULL;
// 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);
}