www.pudn.com > NEROSDK5582.ZIP > IsoTrack.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: IsoTrack.cpp
|*
|* PURPOSE: ISO tree handling
******************************************************************************/
#include "stdafx.h"
#include "BurnContext.h"
#include "FindFile.h"
// This function creates a CNeroIsoTrack from the user supplied parameters.
// It imports previous session (if any) and builds the file and directory
// tree.
EXITCODE CBurnContext::GetIsoTrack (const PARAMETERS & params, CNeroIsoTrack** ppIsoTrack, NERO_ISO_ITEM** ppItem)
{
*ppIsoTrack = NULL;
// Only import a session if a session number has been provided
if (-1 != params.GetSessionToImport())
{
// Make sure that NeroGetCDInfo has not been called before to prevent multiple
// allocation of memory for NERO_CD_INFO.
_ASSERTE (m_NeroCDInfo == NULL);
// First get the CD info to obtain information about all available sessions
m_NeroCDInfo = NeroGetCDInfo (m_NeroDeviceHandle, 0);
if (NULL == m_NeroCDInfo)
{
return EXITCODE_ERROR_GETTING_CD_INFO;
}
// Check the numbers and make sure that the requested session exists.
if (params.GetSessionToImport() > (int)(m_NeroCDInfo->ncdiNumTracks))
{
return EXITCODE_BAD_IMPORT_SESSION_NUMBER;
}
DWORD dwFlags = 0;
// Determine the format to be imported
if (true == params.GetImportRockridge())
{
dwFlags |= NIITEF_IMPORT_ROCKRIDGE;
}
if (true == params.GetImportIsoOnly())
{
dwFlags |= NIITEF_IMPORT_ISO_ONLY;
}
if (true == params.GetPreferRockRidge())
{
dwFlags |= NIITEF_PREFER_ROCKRIDGE;
}
// Now, import the session. If the function fails, it's probably
// due to no CD in drive.
// NeroImportIsoTrackEx creates 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.
// m_pCDStamp will be filled with a pointer to a CDStamp object
// which will have to be freed later by the CBurnContext destructor.
// ppItem is a reference to a pointer to a NERO_ISO_ITEM
// So to get the required pointer to a NERO_ISO_ITEM we have to
// de-reference ppItem once.
*ppItem = NeroImportIsoTrackEx (m_NeroDeviceHandle,
params.GetSessionToImport(),
&m_pCDStamp,
dwFlags);
// The NERO_ISO_ITEM pointer must not be NULL
if (NULL == *ppItem)
{
GetLastErrorLogLine();
return EXITCODE_NO_CD_INSERTED;
}
} // if (-1 != params.m_iSessionToImport)
// Iterate through the file list and it each one to the tree.
// If directory is stumbled upon, recurse it and it all of
// its contents.
for (int i = 0; i < params.GetFileListSize(); i ++)
{
NERO_ISO_ITEM* pItem;
EXITCODE code;
// Create a tree from the filename supplied.
code = CreateIsoTree (params.GetFileList().vect[i], &pItem);
// If there was a problem creating the tree then delete
// the whole tree that has been created so far and
// return the error code.
if (code != EXITCODE_OK)
{
DeleteIsoItemTree (*ppItem);
return code;
}
// Add the file to the beginning of the root directory.
if (NULL != *ppItem)
{
pItem->nextItem = *ppItem;
}
*ppItem = pItem;
}
if (NULL != *ppItem)
{
DWORD dwFlags = 0;
if (true == params.GetUseJoliet())
{
dwFlags |= NCITEF_USE_JOLIET;
}
if (true == params.GetUseMode2())
{
dwFlags |= NCITEF_USE_MODE2;
}
if (true == params.GetUseRockridge())
{
dwFlags |= NCITEF_USE_ROCKRIDGE;
}
if (true == params.GetCreateIsoFs())
{
dwFlags |= NCITEF_CREATE_ISO_FS;
}
if (true == params.GetCreateUdfFS())
{
dwFlags |= NCITEF_CREATE_UDF_FS;
}
// Finally, create the ISO track.
*ppIsoTrack = NeroCreateIsoTrackEx (*ppItem,
params.GetVolumeName(),
dwFlags);
// If the ISO track could not be created then delete the
// ISO item tree and return with an error
if (NULL == *ppIsoTrack)
{
GetLastErrorLogLine();
DeleteIsoItemTree (*ppItem);
return EXITCODE_FAILED_TO_CREATE_ISO_TRACK;
}
}
return EXITCODE_OK;
}
// This function deletes the iso tree recursively.
void CBurnContext::DeleteIsoItemTree (NERO_ISO_ITEM * pItem)
{
// Step through the tree until the
// ISO item tree pointer becomes NULL
while (NULL != pItem)
{
NERO_ISO_ITEM* pNextItem = pItem->nextItem;
if (TRUE == pItem->isDirectory)
{
// We have encountered another ISO item tree;
// recurse another level.
DeleteIsoItemTree (pItem->subDirFirstItem);
}
if (TRUE == pItem->isReference)
{
NeroFreeMem (pItem);
}
else
{
NeroFreeIsoItem (pItem);
}
pItem = pNextItem;
}
}
// This function searches for a specified path and recursively adds
// all files and directories that our found.
EXITCODE CBurnContext::CreateIsoTree (LPCSTR psFilename, NERO_ISO_ITEM ** ppItem, int iLevel)
{
// CFindFiles is a helper class for file and subdirectory handling
CFindFiles ff (psFilename);
*ppItem = NULL;
if (false == ff.IsValidEntry())
{
if (0 == iLevel)
{
// If we haven't found any entries and we are on the
// first level of recursion then this should be
// reported as an error.
m_ErrorLog.printf ("File specification '%s' resulted in no matches!\n", psFilename);
return EXITCODE_FILE_NOT_FOUND;
}
else
{
// If we are on a level other than first, it is ok
// not to find any entries. This simply means we
// stumbled upon an empty directory.
return EXITCODE_OK;
}
}
char sPath[MAX_PATH];
// Make sure that we have no relative path names, but only absolute paths
if (NULL == _fullpath (sPath, psFilename, sizeof (sPath)))
{
// Our path buffer is too small. Bail out!
return EXITCODE_INTERNAL_ERROR;
}
// Find the last blackslash and remove it if found.
// This will leave us with a root directory.
LPSTR psBackslash = strrchr (sPath, '\\');
if (NULL != psBackslash)
{
*psBackslash = 0;
}
do
{
char sNewPath[MAX_PATH];
strcpy (sNewPath, sPath);
// We need to calculate whether the string will fit.
if (strlen (ff.m_fd.name) + strlen (sNewPath) + 1 >= sizeof (sNewPath))
{
DeleteIsoItemTree (*ppItem);
return EXITCODE_INTERNAL_ERROR;
}
strcat (sNewPath, "\\");
strcat (sNewPath, ff.m_fd.name);
if (true == ff.IsSubDir())
{
// Here we handle subdirectories
// strcmp returns 0 on equal strings.
// Proceed if name contains none of "." or ".."
if ((0 != strcmp (ff.m_fd.name, ".")) && (0 != strcmp (ff.m_fd.name, "..")))
{
// We need to calculate whether the string will fit.
if (strlen (sNewPath) + 2 >= sizeof (sNewPath))
{
DeleteIsoItemTree (*ppItem);
return EXITCODE_INTERNAL_ERROR;
}
// Append a wildcard to the path and do a recursive search.
strcat (sNewPath, "\\*");
NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem ();
if (NULL == pNewItem)
{
DeleteIsoItemTree (*ppItem);
return EXITCODE_OUT_OF_MEMORY;
}
memset (pNewItem, 0, sizeof (*pNewItem));
// Attach this item to the beginning of the list.
if (*ppItem)
{
pNewItem->nextItem = *ppItem;
}
*ppItem = pNewItem;
pNewItem->isDirectory = TRUE;
pNewItem->entryTime = *localtime (&ff.m_fd.time_create);
strcpy (pNewItem->fileName, ff.m_fd.name);
// Create an ISO item tree at a deeper level
EXITCODE code = CreateIsoTree (sNewPath, &pNewItem->subDirFirstItem, iLevel + 1);
if (EXITCODE_OK != code)
{
DeleteIsoItemTree (*ppItem);
return code;
}
}
}
else
{
// Here we handle regular files
NERO_ISO_ITEM * pNewItem = NeroCreateIsoItem ();
if (NULL == pNewItem)
{
DeleteIsoItemTree (*ppItem);
return EXITCODE_OUT_OF_MEMORY;
}
memset (pNewItem, 0, sizeof (*pNewItem));
strcpy (pNewItem->sourceFilePath, sNewPath);
pNewItem->isDirectory = FALSE;
pNewItem->entryTime = *localtime (&ff.m_fd.time_create);
strcpy (pNewItem->fileName, ff.m_fd.name);
// Attach this item to the beginning of the list.
if (*ppItem)
{
pNewItem->nextItem = *ppItem;
}
*ppItem = pNewItem;
}
ff.FindNext ();
}
while (ff.IsValidEntry ());
return EXITCODE_OK;
}