aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascRootFile_TVFS.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2019-08-10 19:01:24 +0200
committerShauren <shauren.trinity@gmail.com>2019-08-10 19:01:24 +0200
commitcd720efbfa60f434f420ab66e220eca742c48e45 (patch)
tree3c960ac5249d0711b71fbfdc62f6c0b665ed85ee /dep/CascLib/src/CascRootFile_TVFS.cpp
parent0d6320dfd3932865edb69c8528327b767bd476ef (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@b91f87c770c78340dcd96df970e55b5c0469e884
Diffstat (limited to 'dep/CascLib/src/CascRootFile_TVFS.cpp')
-rw-r--r--dep/CascLib/src/CascRootFile_TVFS.cpp309
1 files changed, 171 insertions, 138 deletions
diff --git a/dep/CascLib/src/CascRootFile_TVFS.cpp b/dep/CascLib/src/CascRootFile_TVFS.cpp
index 38d32120805..25ccf450397 100644
--- a/dep/CascLib/src/CascRootFile_TVFS.cpp
+++ b/dep/CascLib/src/CascRootFile_TVFS.cpp
@@ -98,19 +98,6 @@ typedef struct _TVFS_PATH_TABLE_ENTRY
DWORD NodeValue; // Node value
} TVFS_PATH_TABLE_ENTRY, *PTVFS_PATH_TABLE_ENTRY;
-// In-memory layout of VFS span entry
-typedef struct _TVFS_SPAN_ENTRY
-{
- LPBYTE pbCftFileTable;
- LPBYTE pbCftFileEntry;
- LPBYTE pbCftFileEnd;
-
- DWORD dwFileOffset; // Offset into the referenced file
- DWORD dwSpanSize; // Size of the span
- DWORD dwCftOffset; // Offset relative to the beginning of the container file table
-
-} TVFS_SPAN_ENTRY, *PTVFS_SPAN_ENTRY;
-
//-----------------------------------------------------------------------------
// Handler definition for TVFS root file
@@ -123,10 +110,9 @@ struct TRootHandler_TVFS : public TFileTreeRoot
{
// TVFS supports file names, but DOESN'T support CKeys.
dwFeatures |= CASC_FEATURE_FILE_NAMES;
- dwNestLevel = 0;
}
- // Returns size of "container file table offset" fiels in the VFS.
+ // Returns size of "container file table offset" field in the VFS.
// - If the container file table is larger than 0xffffff bytes, it's 4 bytes
// - If the container file table is larger than 0xffff bytes, it's 3 bytes
// - If the container file table is larger than 0xff bytes, it's 2 bytes
@@ -142,50 +128,24 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return 1;
}
- bool PathBuffer_AddChar(PATH_BUFFER & PathBuffer, char chOneChar)
- {
- if(PathBuffer.szPtr >= PathBuffer.szEnd)
- return false;
-
- *PathBuffer.szPtr++ = chOneChar;
- *PathBuffer.szPtr = 0;
- return true;
- }
-
- bool PathBuffer_AddString(PATH_BUFFER & PathBuffer, LPBYTE pbNamePtr, LPBYTE pbNameEnd)
- {
- size_t nLength = (pbNameEnd - pbNamePtr);
-
- // Check whether we have enough space
- if ((PathBuffer.szPtr + nLength) > PathBuffer.szEnd)
- return false;
-
- // Copy the node name
- memcpy(PathBuffer.szPtr, pbNamePtr, nLength);
- PathBuffer.szPtr += nLength;
- return true;
- }
-
- bool PathBuffer_AppendNode(PATH_BUFFER & PathBuffer, TVFS_PATH_TABLE_ENTRY & PathEntry)
+ bool PathBuffer_AppendNode(CASC_PATH<char> & PathBuffer, TVFS_PATH_TABLE_ENTRY & PathEntry)
{
// Append the prefix separator, if needed
if (PathEntry.NodeFlags & TVFS_PTE_PATH_SEPARATOR_PRE)
- PathBuffer_AddChar(PathBuffer, '/');
+ PathBuffer.AppendChar('/');
// Append the name fragment, if any
if (PathEntry.pbNameEnd > PathEntry.pbNamePtr)
- PathBuffer_AddString(PathBuffer, PathEntry.pbNamePtr, PathEntry.pbNameEnd);
+ PathBuffer.AppendStringN((const char *)PathEntry.pbNamePtr, (PathEntry.pbNameEnd - PathEntry.pbNamePtr), false);
// Append the postfix separator, if needed
if (PathEntry.NodeFlags & TVFS_PTE_PATH_SEPARATOR_POST)
- PathBuffer_AddChar(PathBuffer, '/');
+ PathBuffer.AppendChar('/');
- // Always end the buffer with zero
- PathBuffer.szPtr[0] = 0;
return true;
}
- static int CaptureDirectoryHeader(TVFS_DIRECTORY_HEADER & DirHeader, LPBYTE pbDataPtr, LPBYTE pbDataEnd)
+ static DWORD CaptureDirectoryHeader(TVFS_DIRECTORY_HEADER & DirHeader, LPBYTE pbDataPtr, LPBYTE pbDataEnd)
{
// Fill the header structure with zeros
memset(&DirHeader, 0, sizeof(TVFS_DIRECTORY_HEADER));
@@ -262,32 +222,50 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return (1 <= SpanCount && SpanCount <= 224) ? pbVfsFileEntry : NULL;
}
- LPBYTE CaptureVfsSpanEntry(TVFS_DIRECTORY_HEADER & DirHeader, LPBYTE pbVfsSpanEntry, TVFS_SPAN_ENTRY & SpanEntry)
+ LPBYTE CaptureVfsSpanEntries(TVFS_DIRECTORY_HEADER & DirHeader, LPBYTE pbVfsSpanEntry, PCASC_CKEY_ENTRY PtrSpanEntry, size_t SpanCount)
{
+ LPBYTE pbCftFileTable;
+ LPBYTE pbCftFileEntry;
+ LPBYTE pbCftFileEnd;
LPBYTE pbVfsFileTable = DirHeader.pbDirectoryData + DirHeader.VfsTableOffset;
LPBYTE pbVfsFileEnd = pbVfsFileTable + DirHeader.VfsTableSize;
size_t ItemSize = sizeof(DWORD) + sizeof(DWORD) + DirHeader.CftOffsSize;
- // Check the range being captured
- if(pbVfsSpanEntry < pbVfsFileTable || (pbVfsSpanEntry + ItemSize) > pbVfsFileEnd)
+ // Check whether all spans are included in the valid range
+ if(pbVfsSpanEntry < pbVfsFileTable || (pbVfsSpanEntry + (ItemSize * SpanCount)) > pbVfsFileEnd)
return NULL;
- //
- // Structure of the span entry:
- // (4bytes): Offset into the referenced file (big endian)
- // (4bytes): Size of the span (big endian)
- // (?bytes): Offset into Container File Table. Length depends on container file table size
- //
-
- SpanEntry.dwFileOffset = ConvertBytesToInteger_4(pbVfsSpanEntry);
- SpanEntry.dwSpanSize = ConvertBytesToInteger_4(pbVfsSpanEntry + sizeof(DWORD));
- SpanEntry.dwCftOffset = ConvertBytesToInteger_X(pbVfsSpanEntry + sizeof(DWORD) + sizeof(DWORD), DirHeader.CftOffsSize);
-
- // Resolve the Container File Table entries
- SpanEntry.pbCftFileTable = DirHeader.pbDirectoryData + DirHeader.CftTableOffset;
- SpanEntry.pbCftFileEntry = SpanEntry.pbCftFileTable + SpanEntry.dwCftOffset;
- SpanEntry.pbCftFileEnd = SpanEntry.pbCftFileTable + DirHeader.CftTableSize;
- return pbVfsSpanEntry + ItemSize;
+ // Convert all spans
+ for(size_t i = 0; i < SpanCount; i++)
+ {
+ DWORD dwCftOffset = ConvertBytesToInteger_X(pbVfsSpanEntry + sizeof(DWORD) + sizeof(DWORD), DirHeader.CftOffsSize);
+
+ //
+ // Structure of the span entry:
+ // (4bytes): Offset into the referenced file (big endian)
+ // (4bytes): Size of the span (big endian)
+ // (?bytes): Offset into Container File Table. Length depends on container file table size
+ //
+
+ // Resolve the Container File Table entry
+ pbCftFileTable = DirHeader.pbDirectoryData + DirHeader.CftTableOffset;
+ pbCftFileEntry = pbCftFileTable + dwCftOffset;
+ pbCftFileEnd = pbCftFileTable + DirHeader.CftTableSize;
+
+ // Capture the EKey and the file size
+ if((pbCftFileEntry + DirHeader.EKeySize + sizeof(DWORD)) > pbCftFileEnd)
+ return NULL;
+
+ // Copy the EKey and content size
+ CaptureEncodedKey(PtrSpanEntry->EKey, pbCftFileEntry, DirHeader.EKeySize);
+ PtrSpanEntry->ContentSize = ConvertBytesToInteger_4(pbVfsSpanEntry + sizeof(DWORD));
+
+ // Move to the next entry
+ pbVfsSpanEntry += ItemSize;
+ PtrSpanEntry++;
+ }
+
+ return pbVfsSpanEntry;
}
//
@@ -365,7 +343,7 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return pbPathTablePtr;
}
- bool IsVfsFileEKey(TCascStorage * hs, ENCODED_KEY & EKey, size_t EKeyLength)
+ bool IsVfsFileEKey(TCascStorage * hs, LPBYTE EKey, size_t EKeyLength)
{
PCASC_CKEY_ENTRY pCKeyEntry;
size_t ItemCount = hs->VfsRootList.ItemCount();
@@ -376,7 +354,7 @@ struct TRootHandler_TVFS : public TFileTreeRoot
pCKeyEntry = (PCASC_CKEY_ENTRY)hs->VfsRootList.ItemAt(i);
if (pCKeyEntry != NULL)
{
- if (!memcmp(pCKeyEntry->EKey, EKey.Value, EKeyLength))
+ if (!memcmp(pCKeyEntry->EKey, EKey, EKeyLength))
return true;
}
}
@@ -387,27 +365,27 @@ struct TRootHandler_TVFS : public TFileTreeRoot
// This function verifies whether a file is actually a sub-directory.
// If yes, it contains just another "TVFS" virtual file system, just like the ROOT file.
- int IsVfsSubDirectory(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, TVFS_DIRECTORY_HEADER & SubHeader, ENCODED_KEY & EKey, DWORD dwFileSize)
+ DWORD IsVfsSubDirectory(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, TVFS_DIRECTORY_HEADER & SubHeader, LPBYTE EKey, DWORD dwFileSize)
{
PCASC_CKEY_ENTRY pCKeyEntry;
LPBYTE pbVfsData = NULL;
DWORD cbVfsData = dwFileSize;
- int nError = ERROR_BAD_FORMAT;
+ DWORD dwErrCode = ERROR_BAD_FORMAT;
// Verify whether the EKey is in the list of VFS root files
if(IsVfsFileEKey(hs, EKey, DirHeader.EKeySize))
{
// Locate the CKey entry
- if((pCKeyEntry = FindCKeyEntry_EKey(hs, EKey.Value)) != NULL)
+ if((pCKeyEntry = FindCKeyEntry_EKey(hs, EKey)) != NULL)
{
// Load the entire file into memory
pbVfsData = LoadInternalFileToMemory(hs, pCKeyEntry, &cbVfsData);
if (pbVfsData && cbVfsData)
{
// Capture the file folder. This also serves as test
- nError = CaptureDirectoryHeader(SubHeader, pbVfsData, pbVfsData + cbVfsData);
- if (nError == ERROR_SUCCESS)
- return nError;
+ dwErrCode = CaptureDirectoryHeader(SubHeader, pbVfsData, pbVfsData + cbVfsData);
+ if (dwErrCode == ERROR_SUCCESS)
+ return dwErrCode;
// Clear the captured header
memset(&SubHeader, 0, sizeof(TVFS_DIRECTORY_HEADER));
@@ -416,7 +394,7 @@ struct TRootHandler_TVFS : public TFileTreeRoot
}
}
- return nError;
+ return dwErrCode;
}
void InsertRootVfsEntry(TCascStorage * hs, LPBYTE pbCKey, const char * szFormat, size_t nIndex)
@@ -432,15 +410,18 @@ struct TRootHandler_TVFS : public TFileTreeRoot
}
}
- DWORD ParsePathFileTable(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, PATH_BUFFER & PathBuffer, LPBYTE pbPathTablePtr, LPBYTE pbPathTableEnd)
+ DWORD ParsePathFileTable(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, CASC_PATH<char> & PathBuffer, LPBYTE pbPathTablePtr, LPBYTE pbPathTableEnd)
{
TVFS_DIRECTORY_HEADER SubHeader;
TVFS_PATH_TABLE_ENTRY PathEntry;
PCASC_CKEY_ENTRY pCKeyEntry;
LPBYTE pbVfsSpanEntry;
- char * szSavePathPtr = PathBuffer.szPtr;
- DWORD dwSpanCount = 0;
- int nError;
+ size_t nSavePos = PathBuffer.Save();
+ DWORD dwSpanCount;
+ DWORD dwErrCode;
+
+ // Sanity check
+ assert(SpanArray.IsInitialized());
// Parse the file table
while(pbPathTablePtr < pbPathTableEnd)
@@ -467,9 +448,9 @@ struct TRootHandler_TVFS : public TFileTreeRoot
assert((PathEntry.NodeValue & TVFS_FOLDER_SIZE_MASK) >= sizeof(DWORD));
// Recursively call the folder parser on the same file
- nError = ParsePathFileTable(hs, DirHeader, PathBuffer, pbPathTablePtr, pbDirectoryEnd);
- if (nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = ParsePathFileTable(hs, DirHeader, PathBuffer, pbPathTablePtr, pbDirectoryEnd);
+ if (dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Skip the directory data
pbPathTablePtr = pbDirectoryEnd;
@@ -481,63 +462,117 @@ struct TRootHandler_TVFS : public TFileTreeRoot
if(pbVfsSpanEntry == NULL)
return ERROR_BAD_FORMAT;
- // TODO: Need to support multi-span files larger than 4 GB
- // Example: CoD: Black Ops 4, file "zone/base.xpak" 0x16 spans, over 15 GB size
- assert(dwSpanCount == 1);
- dwSpanCount = 1;
-
- // Parse all span entries
- for(DWORD i = 0; i < dwSpanCount; i++)
+ // If it's one span, it's either a subdirectory or an entire file
+ if(dwSpanCount == 1)
{
- TVFS_SPAN_ENTRY SpanEntry;
- ENCODED_KEY EKey = {0};
+ CASC_CKEY_ENTRY SpanEntry;
- // Capture the n-th span entry
- pbVfsSpanEntry = CaptureVfsSpanEntry(DirHeader, pbVfsSpanEntry, SpanEntry);
+ // Capture the single span entry
+ pbVfsSpanEntry = CaptureVfsSpanEntries(DirHeader, pbVfsSpanEntry, &SpanEntry, 1);
if(pbVfsSpanEntry == NULL)
return ERROR_FILE_CORRUPT;
- // Capture the encoded key
- if((SpanEntry.pbCftFileEntry + DirHeader.EKeySize) > SpanEntry.pbCftFileEnd)
- return ERROR_BAD_FORMAT;
+ // Find the CKey entry
+ pCKeyEntry = FindCKeyEntry_EKey(hs, SpanEntry.EKey);
+ if(pCKeyEntry != NULL)
+ {
+ // We need to check whether this is another TVFS directory file
+ if (IsVfsSubDirectory(hs, DirHeader, SubHeader, SpanEntry.EKey, SpanEntry.ContentSize) == ERROR_SUCCESS)
+ {
+ // Add colon (':')
+ PathBuffer.AppendChar(':');
+
+ // The file content size should already be there
+ assert(pCKeyEntry->ContentSize == SpanEntry.ContentSize);
+ FileTree.InsertByName(pCKeyEntry, PathBuffer);
- // Copy the EKey
- memcpy(EKey.Value, SpanEntry.pbCftFileEntry, DirHeader.EKeySize);
+ // Parse the subdir
+ ParseDirectoryData(hs, SubHeader, PathBuffer);
+ CASC_FREE(SubHeader.pbDirectoryData);
+ }
+ else
+ {
+ // If the content content size is not there, supply it now
+ if(pCKeyEntry->ContentSize == CASC_INVALID_SIZE)
+ pCKeyEntry->ContentSize = SpanEntry.ContentSize;
+ FileTree.InsertByName(pCKeyEntry, PathBuffer);
+ }
+ }
+ }
+ else
+ {
+ PCASC_CKEY_ENTRY pSpanEntries;
+ PCASC_FILE_NODE pFileNode;
+ USHORT RefCount;
+ bool bFilePresent = true;
+
+ //
+ // Need to support multi-span files, possibly lager than 4 GB
+ // Example: CoD: Black Ops 4, file "zone/base.xpak" 0x16 spans, over 15 GB size
+ //
+
+ // Allocate buffer for all span entries
+ pSpanEntries = (PCASC_CKEY_ENTRY)SpanArray.Insert(dwSpanCount);
+ if(pSpanEntries == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ // Capture all span entries
+ pbVfsSpanEntry = CaptureVfsSpanEntries(DirHeader, pbVfsSpanEntry, pSpanEntries, dwSpanCount);
+ if(pbVfsSpanEntry == NULL)
+ return ERROR_FILE_CORRUPT;
- // We need to check whether this is another TVFS directory file
- if (IsVfsSubDirectory(hs, DirHeader, SubHeader, EKey, SpanEntry.dwSpanSize) == ERROR_SUCCESS)
+ // Parse all span entries
+ for(DWORD dwSpanIndex = 0; dwSpanIndex < dwSpanCount; dwSpanIndex++)
{
- // Add colon (':')
- PathBuffer_AddChar(PathBuffer, ':');
+ PCASC_CKEY_ENTRY pSpanEntry = pSpanEntries + dwSpanIndex;
- // Insert the file to the file tree
- if((pCKeyEntry = FindCKeyEntry_EKey(hs, EKey.Value)) != NULL)
+ // Find the CKey entry
+ pCKeyEntry = FindCKeyEntry_EKey(hs, pSpanEntries[dwSpanIndex].EKey);
+ if(pCKeyEntry == NULL)
{
- // The file content size should already be there
- assert(pCKeyEntry->ContentSize == SpanEntry.dwSpanSize);
- FileTree.InsertByName(pCKeyEntry, PathBuffer.szBegin);
+ bFilePresent = false;
+ break;
}
- ParseDirectoryData(hs, SubHeader, PathBuffer);
- CASC_FREE(SubHeader.pbDirectoryData);
- }
- else
- {
- // Insert the file to the file tree
- if((pCKeyEntry = FindCKeyEntry_EKey(hs, EKey.Value)) != NULL)
+ // Supply the content size
+ if(pCKeyEntry->ContentSize == CASC_INVALID_SIZE)
+ pCKeyEntry->ContentSize = pSpanEntry->ContentSize;
+ assert(pCKeyEntry->ContentSize == pSpanEntry->ContentSize);
+
+ // Fill-in the span entry
+ if(dwSpanIndex == 0)
{
- // If the file content is not there, supply it now
- if(pCKeyEntry->ContentSize == CASC_INVALID_SIZE)
- pCKeyEntry->ContentSize = SpanEntry.dwSpanSize;
- FileTree.InsertByName(pCKeyEntry, PathBuffer.szBegin);
+ pCKeyEntry->SpanCount = (BYTE)(dwSpanCount);
+ pCKeyEntry->RefCount++;
}
+ else
+ {
+ // Mark the CKey entry as a file span. Note that a CKey entry
+ // can actually be both a file span and a standalone file:
+ // * zone/zm_red.xpak - { zone/zm_red.xpak_1, zone/zm_red.xpak_2, ..., zone/zm_red.xpak_6 }
+ pCKeyEntry->Flags |= CASC_CE_FILE_SPAN;
+ }
+
+ // Copy all from the existing CKey entry
+ memcpy(pSpanEntry, pCKeyEntry, sizeof(CASC_CKEY_ENTRY));
+ }
+
+ // Do nothing if the file is not present locally
+ if(bFilePresent)
+ {
+ // Insert a new file node that will contain pointer to the span entries
+ RefCount = pSpanEntries->RefCount;
+ pFileNode = FileTree.InsertByName(pSpanEntries, PathBuffer);
+ pSpanEntries->RefCount = RefCount;
+
+ if(pFileNode == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
}
}
}
// Reset the position of the path buffer
- PathBuffer.szPtr = szSavePathPtr;
- PathBuffer.szPtr[0] = 0;
+ PathBuffer.Restore(nSavePos);
}
}
@@ -545,7 +580,7 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return ERROR_SUCCESS;
}
- int ParseDirectoryData(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, PATH_BUFFER & PathBuffer)
+ DWORD ParseDirectoryData(TCascStorage * hs, TVFS_DIRECTORY_HEADER & DirHeader, CASC_PATH<char> & PathBuffer)
{
LPBYTE pbRootDirectory = DirHeader.pbDirectoryData + DirHeader.PathTableOffset;
LPBYTE pbRootDirPtr = pbRootDirectory;
@@ -583,21 +618,19 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return ParsePathFileTable(hs, DirHeader, PathBuffer, pbRootDirPtr, pbRootDirEnd);
}
- int Load(TCascStorage * hs, TVFS_DIRECTORY_HEADER & RootHeader)
+ DWORD Load(TCascStorage * hs, TVFS_DIRECTORY_HEADER & RootHeader)
{
-// PCASC_CKEY_ENTRY pCKeyEntry;
- PATH_BUFFER PathBuffer;
- char szPathBuffer[MAX_PATH];
-
- // Initialize the path buffer
- memset(szPathBuffer, 0, sizeof(szPathBuffer));
- PathBuffer.szBegin =
- PathBuffer.szPtr = szPathBuffer;
- PathBuffer.szEnd = szPathBuffer + MAX_PATH;
+ CASC_PATH<char> PathBuffer;
+ DWORD dwErrCode;
// Save the length of the key
FileTree.SetKeyLength(RootHeader.EKeySize);
+ // Initialize the array of span entries
+ dwErrCode = SpanArray.Create(sizeof(CASC_CKEY_ENTRY), 0x100);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
+
// Insert the main VFS root file as named entry
InsertRootVfsEntry(hs, hs->VfsRoot.CKey, "vfs-root", 0);
@@ -612,29 +645,29 @@ struct TRootHandler_TVFS : public TFileTreeRoot
return ParseDirectoryData(hs, RootHeader, PathBuffer);
}
- DWORD dwNestLevel;
+ CASC_ARRAY SpanArray; // Array of CASC_SPAN_ENTRY for all multi-span files
};
//-----------------------------------------------------------------------------
// Public functions - TVFS root
-int RootHandler_CreateTVFS(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
+DWORD RootHandler_CreateTVFS(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
{
TRootHandler_TVFS * pRootHandler = NULL;
TVFS_DIRECTORY_HEADER RootHeader;
- int nError;
+ DWORD dwErrCode;
// Capture the entire root directory
- nError = TRootHandler_TVFS::CaptureDirectoryHeader(RootHeader, pbRootFile, pbRootFile + cbRootFile);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = TRootHandler_TVFS::CaptureDirectoryHeader(RootHeader, pbRootFile, pbRootFile + cbRootFile);
+ if(dwErrCode == ERROR_SUCCESS)
{
// Allocate the root handler object
pRootHandler = new TRootHandler_TVFS();
if(pRootHandler != NULL)
{
// Load the root directory. If load failed, we free the object
- nError = pRootHandler->Load(hs, RootHeader);
- if(nError != ERROR_SUCCESS)
+ dwErrCode = pRootHandler->Load(hs, RootHeader);
+ if(dwErrCode != ERROR_SUCCESS)
{
delete pRootHandler;
pRootHandler = NULL;
@@ -644,5 +677,5 @@ int RootHandler_CreateTVFS(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFil
// Assign the root directory (or NULL) and return error
hs->pRootHandler = pRootHandler;
- return nError;
+ return dwErrCode;
}