Tools/Extractors: Intruduce safe casc handles and fix all casc related memory leaks

CID 1254545
CID 1254555
CID 1254588
CID 1343649
This commit is contained in:
Shauren
2017-01-18 17:18:20 +01:00
parent 9eda3d8542
commit 3fd51db845
26 changed files with 311 additions and 156 deletions

View File

@@ -9,6 +9,7 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
add_subdirectory(connection_patcher)
add_subdirectory(extractor_common)
add_subdirectory(map_extractor)
add_subdirectory(vmap4_assembler)
add_subdirectory(vmap4_extractor)

View File

@@ -0,0 +1,21 @@
# Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
CollectSourceFiles(
${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE_SOURCES)
add_library(extractor_common STATIC ${PRIVATE_SOURCES})
target_link_libraries(extractor_common boost casc)
target_include_directories(extractor_common
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR})

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CascHandles.h"
#include "CascLib.h"
#include <boost/filesystem/operations.hpp>
namespace
{
const char* HumanReadableCASCError(int error)
{
switch (error)
{
case ERROR_SUCCESS: return "SUCCESS";
case ERROR_FILE_CORRUPT: return "FILE_CORRUPT";
case ERROR_CAN_NOT_COMPLETE: return "CAN_NOT_COMPLETE";
case ERROR_HANDLE_EOF: return "HANDLE_EOF";
case ERROR_NO_MORE_FILES: return "NO_MORE_FILES";
case ERROR_BAD_FORMAT: return "BAD_FORMAT";
case ERROR_INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER";
case ERROR_ALREADY_EXISTS: return "ALREADY_EXISTS";
case ERROR_DISK_FULL: return "DISK_FULL";
case ERROR_INVALID_PARAMETER: return "INVALID_PARAMETER";
case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED";
case ERROR_NOT_ENOUGH_MEMORY: return "NOT_ENOUGH_MEMORY";
case ERROR_INVALID_HANDLE: return "INVALID_HANDLE";
case ERROR_ACCESS_DENIED: return "ACCESS_DENIED";
case ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND";
default: return "UNKNOWN";
}
}
}
void CASC::StorageDeleter::operator()(HANDLE handle)
{
if (handle != nullptr && handle != INVALID_HANDLE_VALUE)
::CascCloseStorage(handle);
}
void CASC::FileDeleter::operator()(HANDLE handle)
{
if (handle != nullptr && handle != INVALID_HANDLE_VALUE)
::CascCloseFile(handle);
}
CASC::StorageHandle CASC::OpenStorage(boost::filesystem::path const& path, DWORD localeMask)
{
HANDLE handle = nullptr;
if (!::CascOpenStorage(path.string().c_str(), localeMask, &handle))
{
DWORD lastError = GetLastError(); // support checking error set by *Open* call, not the next *Close*
printf("Error opening casc storage '%s': %s\n", path.string().c_str(), HumanReadableCASCError(lastError));
CascCloseStorage(handle);
SetLastError(lastError);
return StorageHandle();
}
printf("Opened casc storage '%s'\n", path.string().c_str());
return StorageHandle(handle);
}
CASC::FileHandle CASC::OpenFile(StorageHandle const& storage, char const* fileName, DWORD localeMask, bool printErrors /*= false*/)
{
HANDLE handle = nullptr;
if (!::CascOpenFile(storage.get(), fileName, localeMask, 0, &handle))
{
DWORD lastError = GetLastError(); // support checking error set by *Open* call, not the next *Close*
if (printErrors)
fprintf(stderr, "Failed to open '%s' in CASC storage: %s\n", fileName, HumanReadableCASCError(lastError));
CascCloseFile(handle);
SetLastError(lastError);
return FileHandle();
}
return FileHandle(handle);
}
DWORD CASC::GetFileSize(FileHandle const& file, PDWORD fileSizeHigh)
{
return ::CascGetFileSize(file.get(), fileSizeHigh);
}
bool CASC::ReadFile(FileHandle const& file, void* buffer, DWORD bytes, PDWORD bytesRead)
{
return ::CascReadFile(file.get(), buffer, bytes, bytesRead);
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CascHandles_h__
#define CascHandles_h__
#include "CascPort.h"
#include <memory>
namespace boost
{
namespace filesystem
{
class path;
}
}
namespace CASC
{
struct StorageDeleter
{
typedef HANDLE pointer;
void operator()(HANDLE handle);
};
struct FileDeleter
{
typedef HANDLE pointer;
void operator()(HANDLE handle);
};
typedef std::unique_ptr<HANDLE, StorageDeleter> StorageHandle;
typedef std::unique_ptr<HANDLE, FileDeleter> FileHandle;
StorageHandle OpenStorage(boost::filesystem::path const& path, DWORD localeMask);
FileHandle OpenFile(StorageHandle const& storage, char const* fileName, DWORD localeMask, bool printErrors = false);
DWORD GetFileSize(FileHandle const& file, PDWORD fileSizeHigh);
bool ReadFile(FileHandle const& file, void* buffer, DWORD bytes, PDWORD bytesRead);
}
#endif // CascHandles_h__

View File

@@ -29,7 +29,7 @@ target_include_directories(mapextractor
target_link_libraries(mapextractor
PUBLIC
common
casc)
extractor_common)
CollectIncludeDirectories(
${CMAKE_CURRENT_SOURCE_DIR}

View File

@@ -41,7 +41,7 @@ DB2FileLoader::DB2FileLoader()
fields = nullptr;
}
bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
bool DB2FileLoader::Load(CASC::FileHandle const& db2Handle, DB2Meta const* meta_)
{
if (data)
{
@@ -50,9 +50,9 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
}
DWORD bytesRead = 0;
this->meta = meta;
meta = meta_;
std::uint32_t header;
CascReadFile(db2Handle, &header, sizeof(header), &bytesRead);
CASC::ReadFile(db2Handle, &header, sizeof(header), &bytesRead);
if (bytesRead != sizeof(header)) // Signature
return false;
@@ -61,37 +61,37 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
if (header != 0x35424457)
return false; //'WDB5'
CascReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead);
CASC::ReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead);
if (bytesRead != sizeof(recordCount)) // Number of records
return false;
EndianConvert(recordCount);
CascReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead);
CASC::ReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead);
if (bytesRead != sizeof(fieldCount)) // Number of fields
return false;
EndianConvert(fieldCount);
CascReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead);
CASC::ReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead);
if (bytesRead != sizeof(recordSize)) // Size of a record
return false;
EndianConvert(recordSize);
CascReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead);
CASC::ReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead);
if (bytesRead != sizeof(stringSize)) // String size
return false;
EndianConvert(stringSize);
CascReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead);
CASC::ReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead);
if (bytesRead != sizeof(tableHash)) // Table hash
return false;
EndianConvert(tableHash);
CascReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead);
CASC::ReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead);
if (bytesRead != sizeof(layoutHash)) // Layout hash
return false;
@@ -100,41 +100,41 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
EndianConvert(layoutHash);
CascReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead);
CASC::ReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead);
if (bytesRead != sizeof(minIndex)) // MinIndex WDB2
return false;
EndianConvert(minIndex);
CascReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead);
CASC::ReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead);
if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2
return false;
EndianConvert(maxIndex);
CascReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead);
CASC::ReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead);
if (bytesRead != sizeof(localeMask)) // Locales
return false;
EndianConvert(localeMask);
CascReadFile(db2Handle, &copyIdSize, sizeof(copyIdSize), &bytesRead);
CASC::ReadFile(db2Handle, &copyIdSize, sizeof(copyIdSize), &bytesRead);
if (bytesRead != sizeof(copyIdSize))
return false;
EndianConvert(copyIdSize);
CascReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead);
CASC::ReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead);
if (bytesRead != sizeof(metaFlags))
return false;
EndianConvert(metaFlags);
ASSERT((metaFlags & 0x1) == 0);
ASSERT((meta->IndexField == -1) || (meta->IndexField == (metaFlags >> 16)));
ASSERT((meta->IndexField == -1) || (meta->IndexField == int32((metaFlags >> 16))));
fields = new FieldEntry[fieldCount];
CascReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead);
CASC::ReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead);
if (bytesRead != fieldCount * sizeof(FieldEntry))
return false;
@@ -144,14 +144,14 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
data = new unsigned char[recordSize * recordCount + stringSize];
stringTable = data + recordSize * recordCount;
CascReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead);
CASC::ReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead);
if (bytesRead != recordSize * recordCount + stringSize)
return false;
if (idTableSize)
{
idTable = new unsigned char[idTableSize];
CascReadFile(db2Handle, idTable, idTableSize, &bytesRead);
CASC::ReadFile(db2Handle, idTable, idTableSize, &bytesRead);
if (bytesRead != idTableSize)
return false;
}
@@ -159,7 +159,7 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
if (copyIdSize)
{
copyTable = new unsigned char[copyIdSize];
CascReadFile(db2Handle, copyTable, copyIdSize, &bytesRead);
CASC::ReadFile(db2Handle, copyTable, copyIdSize, &bytesRead);
if (bytesRead != copyIdSize)
return false;
}

View File

@@ -22,6 +22,7 @@
#ifdef PLATFORM_WINDOWS
#undef PLATFORM_WINDOWS
#endif
#include "CascHandles.h"
#include "CascLib.h"
#include "Utilities/ByteConverter.h"
#include "Errors.h"
@@ -32,7 +33,7 @@ class DB2FileLoader
DB2FileLoader();
~DB2FileLoader();
bool Load(HANDLE db2Handle, DB2Meta const* meta);
bool Load(CASC::FileHandle const& db2Handle, DB2Meta const* meta);
class Record
{

View File

@@ -34,6 +34,7 @@
#endif
#include "DBFilesClientList.h"
#include "CascLib.h"
#include "CascHandles.h"
#include "DB2.h"
#include "Banner.h"
#include "StringFormat.h"
@@ -67,7 +68,7 @@ namespace
}
}
HANDLE CascStorage = NULL;
CASC::StorageHandle CascStorage;
typedef struct
{
@@ -259,8 +260,8 @@ uint32 ReadBuild(int locale)
std::string filename = Trinity::StringFormat("component.wow-%s.txt", localeNames[locale]);
//printf("Read %s file... ", filename.c_str());
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, filename.c_str(), CASC_LOCALE_ALL, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, filename.c_str(), CASC_LOCALE_ALL);
if (!dbcFile)
{
printf("Locale %s not installed.\n", localeNames[locale]);
return 0;
@@ -268,7 +269,7 @@ uint32 ReadBuild(int locale)
char buff[512];
DWORD readBytes = 0;
CascReadFile(dbcFile, buff, 512, &readBytes);
CASC::ReadFile(dbcFile, buff, 512, &readBytes);
if (!readBytes)
{
printf("Fatal error: Not found %s file!\n", filename.c_str());
@@ -276,7 +277,6 @@ uint32 ReadBuild(int locale)
}
std::string text = std::string(buff, readBytes);
CascCloseFile(dbcFile);
size_t pos = text.find("version=\"");
size_t pos1 = pos + strlen("version=\"");
@@ -303,10 +303,9 @@ void ReadMapDBC()
{
printf("Read Map.dbc file... ");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, true);
if (!dbcFile)
{
printf("Fatal error: Cannot find Map.dbc in archive! %s\n", HumanReadableCASCError(GetLastError()));
exit(1);
}
@@ -353,17 +352,15 @@ void ReadMapDBC()
}
}
CascCloseFile(dbcFile);
printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size());
}
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, true);
if (!dbcFile)
{
printf("Fatal error: Cannot find LiquidType.dbc in archive! %s\n", HumanReadableCASCError(GetLastError()));
exit(1);
}
@@ -390,7 +387,6 @@ void ReadLiquidTypeTableDBC()
for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x)
LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first];
CascCloseFile(dbcFile);
printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size());
}
@@ -1141,7 +1137,7 @@ void ExtractMaps(uint32 build)
printf("\n");
}
bool ExtractFile(HANDLE fileInArchive, std::string filename)
bool ExtractFile(CASC::FileHandle const& fileInArchive, std::string filename)
{
FILE* output = fopen(filename.c_str(), "wb");
if (!output)
@@ -1155,7 +1151,7 @@ bool ExtractFile(HANDLE fileInArchive, std::string filename)
while (readBytes > 0)
{
CascReadFile(fileInArchive, buffer, sizeof(buffer), &readBytes);
CASC::ReadFile(fileInArchive, buffer, sizeof(buffer), &readBytes);
if (readBytes > 0)
fwrite(buffer, 1, readBytes, output);
}
@@ -1181,19 +1177,16 @@ void ExtractDBFilesClient(int l)
uint32 index = 0;
uint32 count = 0;
char const* fileName = DBFilesClientList[index];
HANDLE dbcFile;
while (fileName)
{
std::string filename = fileName;
if (CascOpenFile(CascStorage, filename.c_str(), WowLocaleToCascLocaleFlags[l], 0, &dbcFile))
if (CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, filename.c_str(), CASC_LOCALE_NONE))
{
filename = outputPath + filename.substr(filename.rfind('\\') + 1);
if (!boost::filesystem::exists(filename))
if (ExtractFile(dbcFile, filename))
++count;
CascCloseFile(dbcFile);
}
else
printf("Unable to open file %s in the archive for locale %s: %s\n", fileName, localeNames[l], HumanReadableCASCError(GetLastError()));
@@ -1254,19 +1247,16 @@ void ExtractGameTables()
uint32 index = 0;
uint32 count = 0;
char const* fileName = GameTables[index];
HANDLE dbcFile;
while (fileName)
{
std::string filename = fileName;
if (CascOpenFile(CascStorage, filename.c_str(), CASC_LOCALE_NONE, 0, &dbcFile))
if (CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, filename.c_str(), CASC_LOCALE_NONE))
{
filename = outputPath + filename.substr(filename.rfind('\\') + 1);
if (!boost::filesystem::exists(filename))
if (ExtractFile(dbcFile, filename))
++count;
CascCloseFile(dbcFile);
}
else
printf("Unable to open file %s in the archive: %s\n", fileName, HumanReadableCASCError(GetLastError()));
@@ -1282,12 +1272,13 @@ bool OpenCascStorage(int locale)
try
{
boost::filesystem::path const storage_dir(boost::filesystem::canonical(input_path) / "Data");
if (!CascOpenStorage(storage_dir.string().c_str(), WowLocaleToCascLocaleFlags[locale], &CascStorage))
CascStorage = CASC::OpenStorage(storage_dir, WowLocaleToCascLocaleFlags[locale]);
if (!CascStorage)
{
printf("error opening casc storage '%s' locale %s: %s\n", storage_dir.string().c_str(), localeNames[locale], HumanReadableCASCError(GetLastError()));
printf("error opening casc storage '%s' locale %s\n", storage_dir.string().c_str(), localeNames[locale]);
return false;
}
printf("opened casc storage '%s' locale %s\n", storage_dir.string().c_str(), localeNames[locale]);
return true;
}
catch (boost::filesystem::filesystem_error& error)
@@ -1327,7 +1318,7 @@ int main(int argc, char * arg[])
build = ReadBuild(i);
if (!build)
{
CascCloseStorage(CascStorage);
CascStorage.reset();
continue;
}
@@ -1339,13 +1330,13 @@ int main(int argc, char * arg[])
uint32 tempBuild = ReadBuild(i);
if (!tempBuild)
{
CascCloseStorage(CascStorage);
CascStorage.reset();
continue;
}
printf("Detected client build %u for locale %s\n\n", tempBuild, localeNames[i]);
ExtractDBFilesClient(i);
CascCloseStorage(CascStorage);
CascStorage.reset();
if (FirstLocale < 0)
{
@@ -1364,14 +1355,14 @@ int main(int argc, char * arg[])
{
OpenCascStorage(FirstLocale);
ExtractGameTables();
CascCloseStorage(CascStorage);
CascStorage.reset();
}
if (CONF_extract & EXTRACT_MAP)
{
OpenCascStorage(FirstLocale);
ExtractMaps(build);
CascCloseStorage(CascStorage);
CascStorage.reset();
}
return 0;

View File

@@ -33,29 +33,21 @@ ChunkedFile::~ChunkedFile()
free();
}
bool ChunkedFile::loadFile(HANDLE mpq, std::string const& fileName, bool log)
bool ChunkedFile::loadFile(CASC::StorageHandle const& mpq, std::string const& fileName, bool log)
{
free();
HANDLE file;
if (!CascOpenFile(mpq, fileName.c_str(), CASC_LOCALE_ALL, 0, &file))
{
if (log)
printf("No such file %s\n", fileName.c_str());
CASC::FileHandle file = CASC::OpenFile(mpq, fileName.c_str(), CASC_LOCALE_ALL, log);
if (!file)
return false;
}
data_size = CascGetFileSize(file, nullptr);
data_size = CASC::GetFileSize(file, nullptr);
data = new uint8[data_size];
CascReadFile(file, data, data_size, nullptr/*bytesRead*/);
CASC::ReadFile(file, data, data_size, nullptr/*bytesRead*/);
parseChunks();
if (prepareLoadedData())
{
CascCloseFile(file);
return true;
}
printf("Error loading %s\n", fileName.c_str());
CascCloseFile(file);
free();
return false;

View File

@@ -23,6 +23,7 @@
#ifdef PLATFORM_WINDOWS
#undef PLATFORM_WINDOWS
#endif
#include "CascHandles.h"
#include "CascLib.h"
#include <map>
#include <string>
@@ -89,7 +90,7 @@ public:
ChunkedFile();
virtual ~ChunkedFile();
bool prepareLoadedData();
bool loadFile(HANDLE mpq, std::string const& fileName, bool log = true);
bool loadFile(CASC::StorageHandle const& mpq, std::string const& fileName, bool log = true);
void free();
void parseChunks();

View File

@@ -23,7 +23,8 @@ target_link_libraries(vmap4extractor
PUBLIC
common
casc
bzip2)
bzip2
extractor_common)
CollectIncludeDirectories(
${CMAKE_CURRENT_SOURCE_DIR}

View File

@@ -41,7 +41,7 @@ DB2FileLoader::DB2FileLoader()
fields = nullptr;
}
bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
bool DB2FileLoader::Load(CASC::FileHandle const& db2Handle, DB2Meta const* meta_)
{
if (data)
{
@@ -50,9 +50,9 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
}
DWORD bytesRead = 0;
this->meta = meta;
meta = meta_;
std::uint32_t header;
CascReadFile(db2Handle, &header, sizeof(header), &bytesRead);
CASC::ReadFile(db2Handle, &header, sizeof(header), &bytesRead);
if (bytesRead != sizeof(header)) // Signature
return false;
@@ -61,37 +61,37 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
if (header != 0x35424457)
return false; //'WDB5'
CascReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead);
CASC::ReadFile(db2Handle, &recordCount, sizeof(recordCount), &bytesRead);
if (bytesRead != sizeof(recordCount)) // Number of records
return false;
EndianConvert(recordCount);
CascReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead);
CASC::ReadFile(db2Handle, &fieldCount, sizeof(fieldCount), &bytesRead);
if (bytesRead != sizeof(fieldCount)) // Number of fields
return false;
EndianConvert(fieldCount);
CascReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead);
CASC::ReadFile(db2Handle, &recordSize, sizeof(recordSize), &bytesRead);
if (bytesRead != sizeof(recordSize)) // Size of a record
return false;
EndianConvert(recordSize);
CascReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead);
CASC::ReadFile(db2Handle, &stringSize, sizeof(stringSize), &bytesRead);
if (bytesRead != sizeof(stringSize)) // String size
return false;
EndianConvert(stringSize);
CascReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead);
CASC::ReadFile(db2Handle, &tableHash, sizeof(tableHash), &bytesRead);
if (bytesRead != sizeof(tableHash)) // Table hash
return false;
EndianConvert(tableHash);
CascReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead);
CASC::ReadFile(db2Handle, &layoutHash, sizeof(layoutHash), &bytesRead);
if (bytesRead != sizeof(layoutHash)) // Layout hash
return false;
@@ -100,41 +100,41 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
EndianConvert(layoutHash);
CascReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead);
CASC::ReadFile(db2Handle, &minIndex, sizeof(minIndex), &bytesRead);
if (bytesRead != sizeof(minIndex)) // MinIndex WDB2
return false;
EndianConvert(minIndex);
CascReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead);
CASC::ReadFile(db2Handle, &maxIndex, sizeof(maxIndex), &bytesRead);
if (bytesRead != sizeof(maxIndex)) // MaxIndex WDB2
return false;
EndianConvert(maxIndex);
CascReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead);
CASC::ReadFile(db2Handle, &localeMask, sizeof(localeMask), &bytesRead);
if (bytesRead != sizeof(localeMask)) // Locales
return false;
EndianConvert(localeMask);
CascReadFile(db2Handle, &copyIdSize, sizeof(copyIdSize), &bytesRead);
CASC::ReadFile(db2Handle, &copyIdSize, sizeof(copyIdSize), &bytesRead);
if (bytesRead != sizeof(copyIdSize))
return false;
EndianConvert(copyIdSize);
CascReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead);
CASC::ReadFile(db2Handle, &metaFlags, sizeof(metaFlags), &bytesRead);
if (bytesRead != sizeof(metaFlags))
return false;
EndianConvert(metaFlags);
ASSERT((metaFlags & 0x1) == 0);
ASSERT((meta->IndexField == -1) || (meta->IndexField == (metaFlags >> 16)));
ASSERT((meta->IndexField == -1) || (meta->IndexField == int32((metaFlags >> 16))));
fields = new FieldEntry[fieldCount];
CascReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead);
CASC::ReadFile(db2Handle, fields, fieldCount * sizeof(FieldEntry), &bytesRead);
if (bytesRead != fieldCount * sizeof(FieldEntry))
return false;
@@ -144,14 +144,14 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
data = new unsigned char[recordSize * recordCount + stringSize];
stringTable = data + recordSize * recordCount;
CascReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead);
CASC::ReadFile(db2Handle, data, recordSize * recordCount + stringSize, &bytesRead);
if (bytesRead != recordSize * recordCount + stringSize)
return false;
if (idTableSize)
{
idTable = new unsigned char[idTableSize];
CascReadFile(db2Handle, idTable, idTableSize, &bytesRead);
CASC::ReadFile(db2Handle, idTable, idTableSize, &bytesRead);
if (bytesRead != idTableSize)
return false;
}
@@ -159,7 +159,7 @@ bool DB2FileLoader::Load(HANDLE db2Handle, DB2Meta const* meta)
if (copyIdSize)
{
copyTable = new unsigned char[copyIdSize];
CascReadFile(db2Handle, copyTable, copyIdSize, &bytesRead);
CASC::ReadFile(db2Handle, copyTable, copyIdSize, &bytesRead);
if (bytesRead != copyIdSize)
return false;
}

View File

@@ -22,6 +22,7 @@
#ifdef PLATFORM_WINDOWS
#undef PLATFORM_WINDOWS
#endif
#include "CascHandles.h"
#include "CascLib.h"
#include "Utilities/ByteConverter.h"
#include "Errors.h"
@@ -32,7 +33,7 @@ class DB2FileLoader
DB2FileLoader();
~DB2FileLoader();
bool Load(HANDLE db2Handle, DB2Meta const* meta);
bool Load(CASC::FileHandle const& db2Handle, DB2Meta const* meta);
class Record
{

View File

@@ -77,7 +77,7 @@ char* GetExtension(char* FileName)
return NULL;
}
extern HANDLE CascStorage;
extern CASC::StorageHandle CascStorage;
ADTFile::ADTFile(char* filename) : ADT(CascStorage, filename, false), nWMO(0), nMDX(0)
{

View File

@@ -19,7 +19,7 @@
#ifndef ADT_H
#define ADT_H
#include "mpqfile.h"
#include "cascfile.h"
#include "wmo.h"
#include "model.h"
@@ -111,7 +111,7 @@ class ADTFile
{
private:
//size_t mcnk_offsets[256], mcnk_sizes[256];
MPQFile ADT;
CASCFile ADT;
//mcell Mcell;
std::string Adtfilename;
public:

View File

@@ -1,15 +1,15 @@
#include "mpqfile.h"
#include "cascfile.h"
#include <deque>
#include <cstdio>
MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/) :
CASCFile::CASCFile(CASC::StorageHandle const& casc, const char* filename, bool warnNoExist /*= true*/) :
eof(false),
buffer(0),
pointer(0),
size(0)
{
HANDLE file;
if (!CascOpenFile(mpq, filename, CASC_LOCALE_ALL, 0, &file))
CASC::FileHandle file = CASC::OpenFile(casc, filename, CASC_LOCALE_ALL, false);
if (!file)
{
if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND)
fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError());
@@ -18,12 +18,11 @@ MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/)
}
DWORD hi = 0;
size = CascGetFileSize(file, &hi);
size = CASC::GetFileSize(file, &hi);
if (hi)
{
fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, uint32(hi));
CascCloseFile(file);
eof = true;
return;
}
@@ -31,25 +30,21 @@ MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/)
if (size <= 1)
{
fprintf(stderr, "Can't open %s, size = %u!\n", filename, uint32(size));
CascCloseFile(file);
eof = true;
return;
}
DWORD read = 0;
buffer = new char[size];
if (!CascReadFile(file, buffer, size, &read) || size != read)
if (!CASC::ReadFile(file, buffer, size, &read) || size != read)
{
fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, uint32(size), uint32(read));
CascCloseFile(file);
eof = true;
return;
}
CascCloseFile(file);
}
size_t MPQFile::read(void* dest, size_t bytes)
size_t CASCFile::read(void* dest, size_t bytes)
{
if (eof) return 0;
@@ -66,19 +61,19 @@ size_t MPQFile::read(void* dest, size_t bytes)
return bytes;
}
void MPQFile::seek(int offset)
void CASCFile::seek(int offset)
{
pointer = offset;
eof = (pointer >= size);
}
void MPQFile::seekRelative(int offset)
void CASCFile::seekRelative(int offset)
{
pointer += offset;
eof = (pointer >= size);
}
void MPQFile::close()
void CASCFile::close()
{
if (buffer) delete[] buffer;
buffer = 0;

View File

@@ -12,6 +12,7 @@
#include <iostream>
#include <deque>
#include <cstdint>
#include "CascHandles.h"
#include "CascLib.h"
typedef int64_t int64;
@@ -29,7 +30,7 @@ typedef uint8_t uint8;
int GetLastError();
#endif
class MPQFile
class CASCFile
{
//MPQHANDLE handle;
bool eof;
@@ -37,12 +38,12 @@ class MPQFile
size_t pointer,size;
// disable copying
MPQFile(const MPQFile &f);
void operator=(const MPQFile &f);
CASCFile(const CASCFile &f) = delete;
CASCFile& operator=(const CASCFile &f) = delete;
public:
MPQFile(HANDLE mpq, const char* filename, bool warnNoExist = true); // filenames are not case sensitive
~MPQFile() { close(); }
CASCFile(CASC::StorageHandle const& casc, const char* filename, bool warnNoExist = true); // filenames are not case sensitive
~CASCFile() { close(); }
size_t read(void* dest, size_t bytes);
size_t getSize() { return size; }
size_t getPos() { return pointer; }

View File

@@ -53,7 +53,7 @@ bool ExtractSingleModel(std::string& fname)
return mdl.ConvertToVMAPModel(output.c_str());
}
extern HANDLE CascStorage;
extern CASC::StorageHandle CascStorage;
struct GameObjectDisplayInfoMeta
{
@@ -82,13 +82,12 @@ enum ModelTypes : uint32
bool GetHeaderMagic(std::string const& fileName, uint32* magic)
{
*magic = 0;
HANDLE file;
if (!CascOpenFile(CascStorage, fileName.c_str(), CASC_LOCALE_ALL, 0, &file))
CASC::FileHandle file = CASC::OpenFile(CascStorage, fileName.c_str(), CASC_LOCALE_ALL);
if (!!file)
return false;
std::unique_ptr<HANDLE, CascFileHandleDeleter> modelFile(file);
DWORD bytesRead = 0;
if (!CascReadFile(file, magic, 4, &bytesRead) || bytesRead != 4)
if (!CASC::ReadFile(file, magic, 4, &bytesRead) || bytesRead != 4)
return false;
return true;
@@ -97,10 +96,9 @@ bool GetHeaderMagic(std::string const& fileName, uint32* magic)
void ExtractGameobjectModels()
{
printf("Extracting GameObject models...");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2", CASC_LOCALE_NONE, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2", CASC_LOCALE_NONE, true);
if (!dbcFile)
{
printf("Fatal error: Cannot find GameObjectDisplayInfo.db2 in archive!\n");
exit(1);
}

View File

@@ -19,12 +19,12 @@
#include "vmapexport.h"
#include "model.h"
#include "wmo.h"
#include "mpqfile.h"
#include "cascfile.h"
#include <cassert>
#include <algorithm>
#include <cstdio>
extern HANDLE CascStorage;
extern CASC::StorageHandle CascStorage;
Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0)
{
@@ -33,7 +33,7 @@ Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0
bool Model::open()
{
MPQFile f(CascStorage, filename.c_str());
CASCFile f(CascStorage, filename.c_str());
if (f.isEof())
{
@@ -154,7 +154,7 @@ Vec3D fixCoordSystem2(Vec3D v)
return Vec3D(v.x, v.z, v.y);
}
ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile)
ModelInstance::ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile)
: id(0), scale(0), flags(0)
{
float ff[3];

View File

@@ -23,7 +23,7 @@
#include "modelheaders.h"
#include <vector>
class MPQFile;
class CASCFile;
Vec3D fixCoordSystem(Vec3D v);
@@ -59,7 +59,7 @@ public:
float sc;
ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {}
ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
ModelInstance(CASCFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
};

View File

@@ -19,7 +19,7 @@
#ifndef MODELHEADERS_H
#define MODELHEADERS_H
#include "mpqfile.h" // integer typedefs
#include "cascfile.h" // integer typedefs
#pragma pack(push,1)

View File

@@ -46,7 +46,7 @@
#include "wdtfile.h"
#include "DB2.h"
#include "wmo.h"
#include "mpqfile.h"
#include "cascfile.h"
#include "vmapexport.h"
#include "Banner.h"
@@ -60,7 +60,7 @@
//-----------------------------------------------------------------------------
HANDLE CascStorage = NULL;
CASC::StorageHandle CascStorage;
typedef struct
{
@@ -165,8 +165,8 @@ uint32 ReadBuild(int locale)
std::string filename = std::string("component.wow-") + localeNames[locale] + ".txt";
//printf("Read %s file... ", filename.c_str());
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, filename.c_str(), CASC_LOCALE_ALL, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, filename.c_str(), CASC_LOCALE_ALL);
if (!dbcFile)
{
printf("Locale %s not installed.\n", localeNames[locale]);
return 0;
@@ -174,7 +174,7 @@ uint32 ReadBuild(int locale)
char buff[512];
DWORD readBytes = 0;
CascReadFile(dbcFile, buff, 512, &readBytes);
CASC::ReadFile(dbcFile, buff, 512, &readBytes);
if (!readBytes)
{
printf("Fatal error: Not found %s file!\n", filename.c_str());
@@ -182,7 +182,6 @@ uint32 ReadBuild(int locale)
}
std::string text = std::string(buff, readBytes);
CascCloseFile(dbcFile);
size_t pos = text.find("version=\"");
size_t pos1 = pos + strlen("version=\"");
@@ -210,12 +209,13 @@ bool OpenCascStorage(int locale)
try
{
boost::filesystem::path const storage_dir(boost::filesystem::canonical(input_path) / "Data");
if (!CascOpenStorage(storage_dir.string().c_str(), WowLocaleToCascLocaleFlags[locale], &CascStorage))
CascStorage = CASC::OpenStorage(storage_dir, WowLocaleToCascLocaleFlags[locale]);
if (!CascStorage)
{
printf("error opening casc storage '%s' locale %s: %s\n", storage_dir.string().c_str(), localeNames[locale], HumanReadableCASCError(GetLastError()));
printf("error opening casc storage '%s' locale %s\n", storage_dir.string().c_str(), localeNames[locale]);
return false;
}
printf("opened casc storage '%s' locale %s\n", storage_dir.string().c_str(), localeNames[locale]);
return true;
}
catch (boost::filesystem::filesystem_error& error)
@@ -225,7 +225,6 @@ bool OpenCascStorage(int locale)
}
}
// Local testing functions
bool FileExists(const char* file)
{
@@ -250,10 +249,9 @@ void strToLower(char* str)
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\LiquidType.db2", CASC_LOCALE_NONE, true);
if (!dbcFile)
{
printf("Fatal error: Cannot find LiquidType.dbc in archive! %s\n", HumanReadableCASCError(GetLastError()));
exit(1);
}
@@ -280,7 +278,6 @@ void ReadLiquidTypeTableDBC()
for (uint32 x = 0; x < db2.GetNumRowCopies(); ++x)
LiqType[db2.GetRowCopy(x).second] = LiqType[db2.GetRowCopy(x).first];
CascCloseFile(dbcFile);
printf("Done! (" SZFMTD " LiqTypes loaded)\n", LiqType.size());
}
@@ -538,7 +535,7 @@ int main(int argc, char ** argv)
uint32 build = ReadBuild(i);
if (!build)
{
CascCloseStorage(CascStorage);
CascStorage.reset();
continue;
}
@@ -574,10 +571,9 @@ int main(int argc, char ** argv)
{
printf("Read Map.dbc file... ");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, 0, &dbcFile))
CASC::FileHandle dbcFile = CASC::OpenFile(CascStorage, "DBFilesClient\\Map.db2", CASC_LOCALE_NONE, true);
if (!dbcFile)
{
printf("Fatal error: Cannot find Map.dbc in archive! %s\n", HumanReadableCASCError(GetLastError()));
exit(1);
}
@@ -624,12 +620,11 @@ int main(int argc, char ** argv)
}
}
CascCloseFile(dbcFile);
printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size());
ParsMapFiles();
}
CascCloseStorage(CascStorage);
CascStorage.reset();
printf("\n");
if (!success)

View File

@@ -30,7 +30,7 @@ char * wdtGetPlainName(char * FileName)
return FileName;
}
extern HANDLE CascStorage;
extern CASC::StorageHandle CascStorage;
WDTFile::WDTFile(char* file_name, char* file_name1):WDT(CascStorage, file_name), gnWMO(0)
{

View File

@@ -19,7 +19,7 @@
#ifndef WDTFILE_H
#define WDTFILE_H
#include "mpqfile.h"
#include "cascfile.h"
#include "wmo.h"
#include <string>
#include <vector>
@@ -30,7 +30,7 @@ class ADTFile;
class WDTFile
{
private:
MPQFile WDT;
CASCFile WDT;
std::string filename;
public:
WDTFile(char* file_name, char* file_name1);

View File

@@ -26,7 +26,7 @@
#include <fstream>
#undef min
#undef max
#include "mpqfile.h"
#include "cascfile.h"
using namespace std;
extern std::vector<uint16> LiqType;
@@ -39,11 +39,11 @@ WMORoot::WMORoot(std::string &filename)
memset(bbcorn2, 0, sizeof(bbcorn2));
}
extern HANDLE CascStorage;
extern CASC::StorageHandle CascStorage;
bool WMORoot::open()
{
MPQFile f(CascStorage, filename.c_str());
CASCFile f(CascStorage, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");
@@ -177,7 +177,7 @@ WMOGroup::WMOGroup(const std::string &filename) :
bool WMOGroup::open()
{
MPQFile f(CascStorage, filename.c_str());
CASCFile f(CascStorage, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");
@@ -511,7 +511,7 @@ WMOGroup::~WMOGroup()
delete [] LiquBytes;
}
WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
WMOInstance::WMOInstance(CASCFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
: currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), id(0), d2(0), d3(0)
{
float ff[3];

View File

@@ -25,7 +25,7 @@
#include <set>
#include <vector>
#include "vec3d.h"
#include "mpqfile.h"
#include "cascfile.h"
// MOPY flags
#define WMO_MATERIAL_NOCAMCOLLIDE 0x01
@@ -38,7 +38,7 @@
class WMOInstance;
class WMOManager;
class MPQFile;
class CASCFile;
/* for whatever reason a certain company just can't stick to one coordinate system... */
static inline Vec3D fixCoords(const Vec3D &v){ return Vec3D(v.z, v.x, v.y); }
@@ -134,7 +134,7 @@ public:
Vec3D pos2, pos3, rot;
uint32 indx, id, d2, d3;
WMOInstance(MPQFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
WMOInstance(CASCFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
static void reset();
};