mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-10-25 13:26:05 +03:00
feat(build): add StormLib (#4)
* feat(app): add StormLib * feat(app): add OpenArchives * feat(util): update SFile to work with StormLib * feat(app): update SFile * feat(util): update SFile with logging (Windows only) * feat(ui): implemented termination w/o notice * chore(build): update StormLib * chore(util): replace std::string with SStr* functions * fix(stormlib): dwFlags argument for SFileOpenPatchArchive * chore(ui): add Script_* stubs * chore(util): clean up SFile::OpenEx * chore(build): update StormLib --------- Co-authored-by: Phaneron <superp00t@tutanota.com>
This commit is contained in:
parent
c5e0034604
commit
f86f6d6d09
@ -15,6 +15,7 @@
|
||||
#include "ui/FrameScript.hpp"
|
||||
#include "ui/FrameXML.hpp"
|
||||
#include "world/World.hpp"
|
||||
#include "util/Filesystem.hpp"
|
||||
#include <bc/Debug.hpp>
|
||||
#include <common/Prop.hpp>
|
||||
#include <storm/Error.hpp>
|
||||
@ -174,6 +175,8 @@ int32_t InitializeGlobal() {
|
||||
|
||||
// ClientServices::LoadCDKey();
|
||||
|
||||
OpenArchives();
|
||||
|
||||
SetPaths();
|
||||
|
||||
ConsoleInitializeClientCommand();
|
||||
|
||||
@ -11,7 +11,7 @@ struct lua_State;
|
||||
#define NUM_SCRIPT_FUNCTIONS_GLUE_SCRIPT_EVENTS 113
|
||||
#define NUM_SCRIPT_FUNCTIONS_REALM_LIST 14
|
||||
#define NUM_SCRIPT_FUNCTIONS_SIMPLE_FRAME 7
|
||||
#define NUM_SCRIPT_FUNCTIONS_SYSTEM 7
|
||||
#define NUM_SCRIPT_FUNCTIONS_SYSTEM 13
|
||||
|
||||
namespace FrameScript {
|
||||
extern FrameScript_Method s_ScriptFunctions_CharCreate[NUM_SCRIPT_FUNCTIONS_CHAR_CREATE];
|
||||
@ -210,5 +210,6 @@ int32_t Script_GetTime(lua_State*);
|
||||
int32_t Script_GetGameTime(lua_State*);
|
||||
int32_t Script_ConsoleExec(lua_State*);
|
||||
int32_t Script_AccessDenied(lua_State*);
|
||||
int32_t Script_GetCurrentResolution(lua_State*);
|
||||
|
||||
#endif
|
||||
|
||||
@ -154,7 +154,9 @@ int32_t Script_ShowTerminationWithoutNoticeNotice(lua_State* L) {
|
||||
}
|
||||
|
||||
int32_t Script_TerminationWithoutNoticeAccepted(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
//WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_AcceptTerminationWithoutNotice(lua_State* L) {
|
||||
|
||||
@ -24,12 +24,42 @@ int32_t Script_AccessDenied(lua_State* L) {
|
||||
return luaL_error(L, "Access Denied");
|
||||
}
|
||||
|
||||
int32_t Script_GetCurrentResolution(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_GetScreenResolutions(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_GetRefreshRates(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_GetCurrentMultisampleFormat(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_GetMultisampleFormats(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
int32_t Script_IsStereoVideoAvailable(lua_State* L) {
|
||||
WHOA_UNIMPLEMENTED(0);
|
||||
}
|
||||
|
||||
FrameScript_Method FrameScript::s_ScriptFunctions_System[NUM_SCRIPT_FUNCTIONS_SYSTEM] = {
|
||||
{ "GetTime", &Script_GetTime },
|
||||
{ "GetGameTime", &Script_GetGameTime },
|
||||
{ "ConsoleExec", &Script_ConsoleExec },
|
||||
{ "ReadFile", &Script_AccessDenied },
|
||||
{ "DeleteFile", &Script_AccessDenied },
|
||||
{ "AppendToFile", &Script_AccessDenied },
|
||||
{ "GetAccountExpansionLevel", &Script_GetAccountExpansionLevel }
|
||||
{ "GetTime", &Script_GetTime },
|
||||
{ "GetGameTime", &Script_GetGameTime },
|
||||
{ "ConsoleExec", &Script_ConsoleExec },
|
||||
{ "ReadFile", &Script_AccessDenied },
|
||||
{ "DeleteFile", &Script_AccessDenied },
|
||||
{ "AppendToFile", &Script_AccessDenied },
|
||||
{ "GetAccountExpansionLevel", &Script_GetAccountExpansionLevel },
|
||||
{ "GetCurrentResolution", &Script_GetCurrentResolution },
|
||||
{ "GetScreenResolutions", &Script_GetScreenResolutions },
|
||||
{ "GetRefreshRates", &Script_GetRefreshRates },
|
||||
{ "GetCurrentMultisampleFormat", &Script_GetCurrentMultisampleFormat },
|
||||
{ "GetMultisampleFormats", &Script_GetMultisampleFormats },
|
||||
{ "IsStereoVideoAvailable", &Script_IsStereoVideoAvailable },
|
||||
};
|
||||
|
||||
@ -25,6 +25,7 @@ target_link_libraries(util
|
||||
PUBLIC
|
||||
freetype-2.0
|
||||
lua-5.1
|
||||
stormlib-9
|
||||
bc
|
||||
common
|
||||
storm
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#include "util/Filesystem.hpp"
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
#include <storm/String.hpp>
|
||||
#include <StormLib.h>
|
||||
|
||||
void* g_mpqHandle = nullptr;
|
||||
|
||||
void OsBuildFontFilePath(const char* fileName, char* buffer, size_t size) {
|
||||
SStrPrintf(buffer, size, "%s\\%s", "Fonts", fileName);
|
||||
@ -24,3 +28,134 @@ char* OsPathFindExtensionWithDot(char* pathName) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void OsFileToNativeSlashes(char* path, size_t size) {
|
||||
#ifdef WHOA_SYSTEM_WIN
|
||||
OsFileToBackSlashes(path, size);
|
||||
#else
|
||||
OsFileToForwardSlashes(path, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsFileToForwardSlashes(char* path, size_t size) {
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (!path[i])
|
||||
return;
|
||||
|
||||
if (path[i] == '\\')
|
||||
path[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
void OsFileToBackSlashes(char* path, size_t size) {
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (!path[i])
|
||||
return;
|
||||
|
||||
if (path[i] == '/')
|
||||
path[i] = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
void OpenExtraArchives(const char* basePath, const char* language, const char* fileNamePrefix) {
|
||||
char path[STORM_MAX_PATH] = { 0 };
|
||||
|
||||
for (unsigned int i = 1; i < 20; ++i) {
|
||||
if (language) {
|
||||
if (i > 1) {
|
||||
SStrPrintf(path, sizeof(path), "%s/%s-%s-%u.MPQ", basePath, fileNamePrefix, language, i);
|
||||
} else {
|
||||
SStrPrintf(path, sizeof(path), "%s/%s-%s.MPQ", basePath, fileNamePrefix, language);
|
||||
}
|
||||
} else {
|
||||
if (i > 1) {
|
||||
SStrPrintf(path, sizeof(path), "%s/%s-%u.MPQ", basePath, fileNamePrefix, i);
|
||||
} else {
|
||||
SStrPrintf(path, sizeof(path), "%s/%s.MPQ", basePath, fileNamePrefix);
|
||||
}
|
||||
}
|
||||
|
||||
OsFileToNativeSlashes(path);
|
||||
if (!SFileOpenPatchArchive(g_mpqHandle, path, nullptr, MPQ_OPEN_NO_LISTFILE))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenArchives()
|
||||
{
|
||||
struct stat info = { 0 };
|
||||
|
||||
const char* languages[] = {
|
||||
"enUS", "enGB", "enTW", "zhTW", "esES",
|
||||
"ruRU", "koKR", "ptPT", "esMX", "itIT",
|
||||
"deDE", "frFR", "enCN", "zhCN", "ptBR"
|
||||
};
|
||||
|
||||
const char* baseFiles[] = {
|
||||
"common.MPQ",
|
||||
"common-2.MPQ",
|
||||
"expansion.MPQ",
|
||||
"lichking.MPQ"
|
||||
};
|
||||
|
||||
const char* extraFiles[] = {
|
||||
"locale",
|
||||
"speech",
|
||||
"expansion-locale",
|
||||
"lichking-locale",
|
||||
"expansion-speech",
|
||||
"lichking-speech",
|
||||
"patch"
|
||||
};
|
||||
|
||||
char path[STORM_MAX_PATH] = { 0 };
|
||||
|
||||
SStrCopy(path, "Data", sizeof(path));
|
||||
if (stat(path, &info) != 0 || (info.st_mode & S_IFDIR) == 0)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < sizeof(baseFiles) / sizeof(baseFiles[0]); ++i) {
|
||||
SStrCopy(path, "Data/", sizeof(path));
|
||||
SStrPack(path, baseFiles[i], sizeof(path));
|
||||
OsFileToNativeSlashes(path);
|
||||
|
||||
if (i == 0) {
|
||||
if (!SFileOpenArchive(path, 0, MPQ_OPEN_NO_LISTFILE, &g_mpqHandle))
|
||||
return;
|
||||
} else if (!SFileOpenPatchArchive(g_mpqHandle, path, nullptr, MPQ_OPEN_NO_LISTFILE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char* language = nullptr;
|
||||
for (size_t i = 0; i < sizeof(languages) / sizeof(languages[0]); ++i) {
|
||||
SStrCopy(path, "Data/", sizeof(path));
|
||||
SStrPack(path, languages[i], sizeof(path));
|
||||
OsFileToNativeSlashes(path);
|
||||
|
||||
if (stat(path, &info) == 0 && (info.st_mode & S_IFDIR) != 0) {
|
||||
language = languages[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (language) {
|
||||
SStrCopy(path, "Data/", sizeof(path));
|
||||
SStrPack(path, language, sizeof(path));
|
||||
|
||||
for (size_t i = 0; i < sizeof(extraFiles) / sizeof(extraFiles[0]); ++i)
|
||||
OpenExtraArchives(path, language, extraFiles[i]);
|
||||
|
||||
// Special case
|
||||
OpenExtraArchives(path, nullptr, "patch");
|
||||
}
|
||||
|
||||
SStrCopy(path, "Data", sizeof(path));
|
||||
OpenExtraArchives(path, nullptr, "patch");
|
||||
}
|
||||
|
||||
@ -8,4 +8,12 @@ void OsBuildFontFilePath(const char*, char*, size_t);
|
||||
|
||||
char* OsPathFindExtensionWithDot(char*);
|
||||
|
||||
void OsFileToNativeSlashes(char* path, size_t size = (size_t) -1);
|
||||
void OsFileToForwardSlashes(char* path, size_t size = (size_t) -1);
|
||||
void OsFileToBackSlashes(char* path, size_t size = (size_t) -1);
|
||||
|
||||
void OpenArchives();
|
||||
|
||||
extern void* g_mpqHandle;
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,27 +1,31 @@
|
||||
#include "util/SFile.hpp"
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <StormLib.h>
|
||||
#include <storm/Memory.hpp>
|
||||
#include <storm/String.hpp>
|
||||
#include <bc/file/File.hpp>
|
||||
#include "util/Filesystem.hpp"
|
||||
|
||||
static char s_basepath[STORM_MAX_PATH] = {0};
|
||||
static char s_datapath[STORM_MAX_PATH] = {0};
|
||||
|
||||
// TODO Proper implementation
|
||||
int32_t SFile::Close(SFile* file) {
|
||||
delete file->m_filename;
|
||||
|
||||
Blizzard::File::Close(file->m_stream);
|
||||
|
||||
SFileCloseFile(file->m_handle);
|
||||
delete file;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO Proper implementation
|
||||
size_t SFile::GetFileSize(SFile* file, size_t* filesizeHigh) {
|
||||
return file->m_size;
|
||||
uint32_t SFile::GetFileSize(SFile* file, uint32_t* filesizeHigh) {
|
||||
DWORD high = 0;
|
||||
DWORD low = SFileGetFileSize(file->m_handle, &high);
|
||||
|
||||
if (filesizeHigh) {
|
||||
*filesizeHigh = high;
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
int32_t SFile::IsStreamingMode() {
|
||||
@ -31,39 +35,47 @@ int32_t SFile::IsStreamingMode() {
|
||||
|
||||
// TODO Proper implementation
|
||||
int32_t SFile::Load(SArchive* archive, const char* filename, void** buffer, size_t* bytes, size_t extraBytes, uint32_t flags, SOVERLAPPED* overlapped) {
|
||||
auto pathLen = SStrLen(filename);
|
||||
char path[STORM_MAX_PATH];
|
||||
SStrCopy(path, filename, sizeof(path));
|
||||
|
||||
uint32_t openflags = BC_FILE_OPEN_MUST_EXIST | BC_FILE_OPEN_SHARE_READ | BC_FILE_OPEN_READ;
|
||||
Blizzard::File::StreamRecord* stream;
|
||||
bool opened = Blizzard::File::Open(path, openflags, stream);
|
||||
size_t size;
|
||||
char* data;
|
||||
|
||||
if (opened) {
|
||||
size = static_cast<size_t>(Blizzard::File::GetFileInfo(stream)->size);
|
||||
|
||||
if (bytes) {
|
||||
*bytes = size;
|
||||
}
|
||||
|
||||
data = new char[size + extraBytes];
|
||||
|
||||
Blizzard::File::SetPos(stream, 0, BC_FILE_SEEK_START);
|
||||
Blizzard::File::Read(stream, data, size, nullptr);
|
||||
Blizzard::File::Close(stream);
|
||||
|
||||
if (extraBytes) {
|
||||
memset(data + size, 0, extraBytes);
|
||||
}
|
||||
|
||||
*buffer = data;
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
if (!buffer || !filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*buffer = nullptr;
|
||||
if (bytes) {
|
||||
*bytes = 0;
|
||||
}
|
||||
|
||||
SFile* file = nullptr;
|
||||
if (!SFile::OpenEx(nullptr, filename, 0, &file)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t high = 0;
|
||||
uint64_t size = SFile::GetFileSize(file, &high);
|
||||
size |= ((uint64_t) high << 32);
|
||||
|
||||
auto data = reinterpret_cast<char*>(SMemAlloc(size + extraBytes, __FILE__, __LINE__, 0));
|
||||
|
||||
if (!SFile::Read(file, data, size, nullptr, nullptr, nullptr)) {
|
||||
SMemFree(data, __FILE__, __LINE__, 0);
|
||||
SFile::Close(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (extraBytes) {
|
||||
memset(data + size, 0, extraBytes);
|
||||
}
|
||||
|
||||
if (bytes) {
|
||||
*bytes = size;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
*buffer = data;
|
||||
}
|
||||
|
||||
SFile::Close(file);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SFile::Open(const char* filename, SFile** file) {
|
||||
@ -72,38 +84,48 @@ int32_t SFile::Open(const char* filename, SFile** file) {
|
||||
|
||||
// TODO Proper implementation
|
||||
int32_t SFile::OpenEx(SArchive* archive, const char* filename, uint32_t flags, SFile** file) {
|
||||
auto pathLen = SStrLen(filename);
|
||||
char path[STORM_MAX_PATH];
|
||||
SStrCopy(path, filename, sizeof(path));
|
||||
|
||||
SFile* fileptr = new SFile;
|
||||
|
||||
fileptr->m_filename = strdup(filename);
|
||||
|
||||
uint32_t openflags = BC_FILE_OPEN_MUST_EXIST | BC_FILE_OPEN_SHARE_READ | BC_FILE_OPEN_READ;
|
||||
|
||||
Blizzard::File::StreamRecord* stream;
|
||||
auto opened = Blizzard::File::Open(fileptr->m_filename, openflags, stream);
|
||||
if (!opened) {
|
||||
*file = nullptr;
|
||||
if (!file || !filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto fileinfo = Blizzard::File::GetFileInfo(stream);
|
||||
char path[STORM_MAX_PATH];
|
||||
|
||||
fileptr->m_stream = stream;
|
||||
fileptr->m_size = fileinfo->size;
|
||||
// Overflow protection
|
||||
if (SStrLen(filename) + 1 > STORM_MAX_PATH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*file = fileptr;
|
||||
SStrCopy(path, filename, STORM_MAX_PATH);
|
||||
OsFileToNativeSlashes(path);
|
||||
|
||||
HANDLE handle;
|
||||
if (!SFileOpenFileEx(nullptr, path, SFILE_OPEN_LOCAL_FILE, &handle)) {
|
||||
OsFileToBackSlashes(path);
|
||||
if (!SFileOpenFileEx(g_mpqHandle, path, SFILE_OPEN_FROM_MPQ, &handle)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*file = new SFile;
|
||||
(*file)->m_handle = handle;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO Proper implementation
|
||||
int32_t SFile::Read(SFile* file, void* buffer, size_t bytestoread, size_t* bytesread, SOVERLAPPED* overlapped, TASYNCPARAMBLOCK* asyncparam) {
|
||||
Blizzard::File::Read(file->m_stream, buffer, bytestoread, bytesread);
|
||||
|
||||
return 1;
|
||||
DWORD read = 0;
|
||||
if (SFileReadFile(file->m_handle, buffer, static_cast<DWORD>(bytestoread), &read, nullptr)) {
|
||||
if (bytesread) {
|
||||
*bytesread = read;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
if (bytesread) {
|
||||
*bytesread = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SFile::Unload(void* ptr) {
|
||||
|
||||
@ -3,8 +3,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
class SArchive;
|
||||
struct SOVERLAPPED;
|
||||
@ -20,7 +18,7 @@ class SFile {
|
||||
public:
|
||||
// Static functions
|
||||
static int32_t Close(SFile*);
|
||||
static size_t GetFileSize(SFile*, size_t*);
|
||||
static uint32_t GetFileSize(SFile*, uint32_t*);
|
||||
static int32_t IsStreamingMode(void);
|
||||
static int32_t Load(SArchive*, const char*, void**, size_t*, size_t, uint32_t, SOVERLAPPED*);
|
||||
static int32_t Open(const char*, SFile**);
|
||||
@ -33,9 +31,7 @@ class SFile {
|
||||
static int32_t GetDataPath(char* path, size_t capacity);
|
||||
|
||||
// Member variables
|
||||
const char* m_filename;
|
||||
Blizzard::File::StreamRecord* m_stream; // TODO Proper implementation
|
||||
uint64_t m_size; // TODO Proper implementation
|
||||
void* m_handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
1
vendor/CMakeLists.txt
vendored
1
vendor/CMakeLists.txt
vendored
@ -1,5 +1,6 @@
|
||||
add_subdirectory(freetype-2.0.9)
|
||||
add_subdirectory(lua-5.1.3)
|
||||
add_subdirectory(stormlib-9)
|
||||
|
||||
if (WHOA_SYSTEM_WIN OR WHOA_SYSTEM_LINUX)
|
||||
set(SDL_SHARED OFF)
|
||||
|
||||
282
vendor/stormlib-9/CMakeLists.txt
vendored
Normal file
282
vendor/stormlib-9/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,282 @@
|
||||
set(LIBRARY_NAME stormlib-9)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(SRC_FILES
|
||||
src/adpcm/adpcm.cpp
|
||||
src/huffman/huff.cpp
|
||||
src/jenkins/lookup3.c
|
||||
src/lzma/C/LzFind.c
|
||||
src/lzma/C/LzmaDec.c
|
||||
src/lzma/C/LzmaEnc.c
|
||||
src/pklib/explode.c
|
||||
src/pklib/implode.c
|
||||
src/sparse/sparse.cpp
|
||||
src/FileStream.cpp
|
||||
src/SBaseCommon.cpp
|
||||
src/SBaseDumpData.cpp
|
||||
src/SBaseFileTable.cpp
|
||||
src/SBaseSubTypes.cpp
|
||||
src/SCompression.cpp
|
||||
src/SFileAddFile.cpp
|
||||
src/SFileAttributes.cpp
|
||||
src/SFileCompactArchive.cpp
|
||||
src/SFileCreateArchive.cpp
|
||||
src/SFileExtractFile.cpp
|
||||
src/SFileFindFile.cpp
|
||||
src/SFileGetFileInfo.cpp
|
||||
src/SFileListFile.cpp
|
||||
src/SFileOpenArchive.cpp
|
||||
src/SFileOpenFileEx.cpp
|
||||
src/SFilePatchArchives.cpp
|
||||
src/SFileReadFile.cpp
|
||||
src/SFileVerify.cpp
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c
|
||||
src/libtomcrypt/src/misc/crypt_libc.c
|
||||
)
|
||||
|
||||
set(TOMCRYPT_FILES
|
||||
src/libtomcrypt/src/hashes/hash_memory.c
|
||||
src/libtomcrypt/src/hashes/md5.c
|
||||
src/libtomcrypt/src/hashes/sha1.c
|
||||
src/libtomcrypt/src/hashes/sha256.c
|
||||
src/libtomcrypt/src/math/ltm_desc.c
|
||||
src/libtomcrypt/src/math/multi.c
|
||||
src/libtomcrypt/src/math/rand_prime.c
|
||||
src/libtomcrypt/src/misc/base64_decode.c
|
||||
src/libtomcrypt/src/misc/crypt_argchk.c
|
||||
src/libtomcrypt/src/misc/crypt_find_hash.c
|
||||
src/libtomcrypt/src/misc/crypt_find_prng.c
|
||||
src/libtomcrypt/src/misc/crypt_hash_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_hash_is_valid.c
|
||||
src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_prng_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_prng_is_valid.c
|
||||
src/libtomcrypt/src/misc/crypt_register_hash.c
|
||||
src/libtomcrypt/src/misc/crypt_register_prng.c
|
||||
src/libtomcrypt/src/misc/zeromem.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_choice.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utctime.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_bit_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_boolean.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_ia5_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_object_identifier.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_octet_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_printable_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_set.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_setof.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_short_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_utctime.c
|
||||
src/libtomcrypt/src/pk/asn1/der_encode_utf8_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_bit_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_boolean.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_octet_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_printable_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_sequence.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utctime.c
|
||||
src/libtomcrypt/src/pk/asn1/der_sequence_free.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_short_integer.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_exptmod.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_free.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_import.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_make_key.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_sign_hash.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
|
||||
)
|
||||
|
||||
set(TOMMATH_FILES
|
||||
src/libtommath/bncore.c
|
||||
src/libtommath/bn_fast_mp_invmod.c
|
||||
src/libtommath/bn_fast_mp_montgomery_reduce.c
|
||||
src/libtommath/bn_fast_s_mp_mul_digs.c
|
||||
src/libtommath/bn_fast_s_mp_mul_high_digs.c
|
||||
src/libtommath/bn_fast_s_mp_sqr.c
|
||||
src/libtommath/bn_mp_2expt.c
|
||||
src/libtommath/bn_mp_abs.c
|
||||
src/libtommath/bn_mp_add.c
|
||||
src/libtommath/bn_mp_addmod.c
|
||||
src/libtommath/bn_mp_add_d.c
|
||||
src/libtommath/bn_mp_and.c
|
||||
src/libtommath/bn_mp_clamp.c
|
||||
src/libtommath/bn_mp_clear.c
|
||||
src/libtommath/bn_mp_clear_multi.c
|
||||
src/libtommath/bn_mp_cmp.c
|
||||
src/libtommath/bn_mp_cmp_d.c
|
||||
src/libtommath/bn_mp_cmp_mag.c
|
||||
src/libtommath/bn_mp_cnt_lsb.c
|
||||
src/libtommath/bn_mp_copy.c
|
||||
src/libtommath/bn_mp_count_bits.c
|
||||
src/libtommath/bn_mp_div.c
|
||||
src/libtommath/bn_mp_div_2.c
|
||||
src/libtommath/bn_mp_div_2d.c
|
||||
src/libtommath/bn_mp_div_3.c
|
||||
src/libtommath/bn_mp_div_d.c
|
||||
src/libtommath/bn_mp_dr_is_modulus.c
|
||||
src/libtommath/bn_mp_dr_reduce.c
|
||||
src/libtommath/bn_mp_dr_setup.c
|
||||
src/libtommath/bn_mp_exch.c
|
||||
src/libtommath/bn_mp_exptmod.c
|
||||
src/libtommath/bn_mp_exptmod_fast.c
|
||||
src/libtommath/bn_mp_expt_d.c
|
||||
src/libtommath/bn_mp_exteuclid.c
|
||||
src/libtommath/bn_mp_fread.c
|
||||
src/libtommath/bn_mp_fwrite.c
|
||||
src/libtommath/bn_mp_gcd.c
|
||||
src/libtommath/bn_mp_get_int.c
|
||||
src/libtommath/bn_mp_grow.c
|
||||
src/libtommath/bn_mp_init.c
|
||||
src/libtommath/bn_mp_init_copy.c
|
||||
src/libtommath/bn_mp_init_multi.c
|
||||
src/libtommath/bn_mp_init_set.c
|
||||
src/libtommath/bn_mp_init_set_int.c
|
||||
src/libtommath/bn_mp_init_size.c
|
||||
src/libtommath/bn_mp_invmod.c
|
||||
src/libtommath/bn_mp_invmod_slow.c
|
||||
src/libtommath/bn_mp_is_square.c
|
||||
src/libtommath/bn_mp_jacobi.c
|
||||
src/libtommath/bn_mp_karatsuba_mul.c
|
||||
src/libtommath/bn_mp_karatsuba_sqr.c
|
||||
src/libtommath/bn_mp_lcm.c
|
||||
src/libtommath/bn_mp_lshd.c
|
||||
src/libtommath/bn_mp_mod.c
|
||||
src/libtommath/bn_mp_mod_2d.c
|
||||
src/libtommath/bn_mp_mod_d.c
|
||||
src/libtommath/bn_mp_montgomery_calc_normalization.c
|
||||
src/libtommath/bn_mp_montgomery_reduce.c
|
||||
src/libtommath/bn_mp_montgomery_setup.c
|
||||
src/libtommath/bn_mp_mul.c
|
||||
src/libtommath/bn_mp_mulmod.c
|
||||
src/libtommath/bn_mp_mul_2.c
|
||||
src/libtommath/bn_mp_mul_2d.c
|
||||
src/libtommath/bn_mp_mul_d.c
|
||||
src/libtommath/bn_mp_neg.c
|
||||
src/libtommath/bn_mp_n_root.c
|
||||
src/libtommath/bn_mp_or.c
|
||||
src/libtommath/bn_mp_prime_fermat.c
|
||||
src/libtommath/bn_mp_prime_is_divisible.c
|
||||
src/libtommath/bn_mp_prime_is_prime.c
|
||||
src/libtommath/bn_mp_prime_miller_rabin.c
|
||||
src/libtommath/bn_mp_prime_next_prime.c
|
||||
src/libtommath/bn_mp_prime_rabin_miller_trials.c
|
||||
src/libtommath/bn_mp_prime_random_ex.c
|
||||
src/libtommath/bn_mp_radix_size.c
|
||||
src/libtommath/bn_mp_radix_smap.c
|
||||
src/libtommath/bn_mp_rand.c
|
||||
src/libtommath/bn_mp_read_radix.c
|
||||
src/libtommath/bn_mp_read_signed_bin.c
|
||||
src/libtommath/bn_mp_read_unsigned_bin.c
|
||||
src/libtommath/bn_mp_reduce.c
|
||||
src/libtommath/bn_mp_reduce_2k.c
|
||||
src/libtommath/bn_mp_reduce_2k_l.c
|
||||
src/libtommath/bn_mp_reduce_2k_setup.c
|
||||
src/libtommath/bn_mp_reduce_2k_setup_l.c
|
||||
src/libtommath/bn_mp_reduce_is_2k.c
|
||||
src/libtommath/bn_mp_reduce_is_2k_l.c
|
||||
src/libtommath/bn_mp_reduce_setup.c
|
||||
src/libtommath/bn_mp_rshd.c
|
||||
src/libtommath/bn_mp_set.c
|
||||
src/libtommath/bn_mp_set_int.c
|
||||
src/libtommath/bn_mp_shrink.c
|
||||
src/libtommath/bn_mp_signed_bin_size.c
|
||||
src/libtommath/bn_mp_sqr.c
|
||||
src/libtommath/bn_mp_sqrmod.c
|
||||
src/libtommath/bn_mp_sqrt.c
|
||||
src/libtommath/bn_mp_sub.c
|
||||
src/libtommath/bn_mp_submod.c
|
||||
src/libtommath/bn_mp_sub_d.c
|
||||
src/libtommath/bn_mp_toom_mul.c
|
||||
src/libtommath/bn_mp_toom_sqr.c
|
||||
src/libtommath/bn_mp_toradix.c
|
||||
src/libtommath/bn_mp_toradix_n.c
|
||||
src/libtommath/bn_mp_to_signed_bin.c
|
||||
src/libtommath/bn_mp_to_signed_bin_n.c
|
||||
src/libtommath/bn_mp_to_unsigned_bin.c
|
||||
src/libtommath/bn_mp_to_unsigned_bin_n.c
|
||||
src/libtommath/bn_mp_unsigned_bin_size.c
|
||||
src/libtommath/bn_mp_xor.c
|
||||
src/libtommath/bn_mp_zero.c
|
||||
src/libtommath/bn_prime_tab.c
|
||||
src/libtommath/bn_reverse.c
|
||||
src/libtommath/bn_s_mp_add.c
|
||||
src/libtommath/bn_s_mp_exptmod.c
|
||||
src/libtommath/bn_s_mp_mul_digs.c
|
||||
src/libtommath/bn_s_mp_mul_high_digs.c
|
||||
src/libtommath/bn_s_mp_sqr.c
|
||||
src/libtommath/bn_s_mp_sub.c
|
||||
)
|
||||
|
||||
set(BZIP2_FILES
|
||||
src/bzip2/blocksort.c
|
||||
src/bzip2/bzlib.c
|
||||
src/bzip2/compress.c
|
||||
src/bzip2/crctable.c
|
||||
src/bzip2/decompress.c
|
||||
src/bzip2/huffman.c
|
||||
src/bzip2/randtable.c
|
||||
)
|
||||
|
||||
set(ZLIB_FILES
|
||||
src/zlib/adler32.c
|
||||
src/zlib/compress.c
|
||||
src/zlib/crc32.c
|
||||
src/zlib/deflate.c
|
||||
src/zlib/inffast.c
|
||||
src/zlib/inflate.c
|
||||
src/zlib/inftrees.c
|
||||
src/zlib/trees.c
|
||||
src/zlib/zutil.c
|
||||
)
|
||||
|
||||
add_definitions(-D_7ZIP_ST -DBZ_STRICT_ANSI)
|
||||
set(LINK_LIBS)
|
||||
|
||||
set(SRC_FILES ${SRC_FILES} ${ZLIB_FILES})
|
||||
set(SRC_FILES ${SRC_FILES} ${BZIP2_FILES})
|
||||
set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES})
|
||||
|
||||
if(WIN32)
|
||||
set(LINK_LIBS ${LINK_LIBS} wininet)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(Free|Net|Open)BSD")
|
||||
message(STATUS "Using BSD port")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate")
|
||||
endif()
|
||||
|
||||
add_library(${LIBRARY_NAME} STATIC ${SRC_FILES} ${SRC_ADDITIONAL_FILES})
|
||||
|
||||
target_link_libraries(${LIBRARY_NAME} ${LINK_LIBS})
|
||||
target_compile_definitions(${LIBRARY_NAME} INTERFACE STORMLIB_NO_AUTO_LINK) #CMake will take care of the linking
|
||||
target_include_directories(${LIBRARY_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
21
vendor/stormlib-9/LICENSE
vendored
Normal file
21
vendor/stormlib-9/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 1999-2013 Ladislav Zezula
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
39
vendor/stormlib-9/README.md
vendored
Normal file
39
vendor/stormlib-9/README.md
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# StormLib
|
||||
|
||||
This is official repository for the StomLib library, an open-source project that can work with Blizzard MPQ archives.
|
||||
|
||||
## Installation and basic usage
|
||||
### Linux
|
||||
1. Download latest release
|
||||
2. Install StormLib:
|
||||
```
|
||||
$ cd <path-to-StormLib>
|
||||
$ cmake CMakeLists.txt
|
||||
$ make
|
||||
$ make install
|
||||
```
|
||||
3. Include StormLib in your project: `#include <StormLib.h>`
|
||||
4. Make sure you compile your project with `-lstorm -lz -lbz2`
|
||||
|
||||
### Windows (Visual Studio 2008)
|
||||
1. Download the latest release of StormLib
|
||||
2. Open the solution file `StormLib_vs08.sln` in Visual Studio 2008
|
||||
3. Choose "Build / Batch Build" and select every build of "StormLib"
|
||||
4. Choose "Rebuild"
|
||||
5. The result libraries are in `.\bin\Win32` and `.\bin\x64`
|
||||
|
||||
### Windows (Visual Studio 2017 or 2019)
|
||||
0. Make sure you have SDK 10.0.17134.0 installed
|
||||
1. Download the latest release of StormLib
|
||||
2. Open the solution file `StormLib_vs19.sln` in Visual Studio 2017/2019
|
||||
3. Choose "Build / Batch Build" and select every build of "StormLib"
|
||||
4. Choose "Rebuild"
|
||||
5. The result libraries are in `.\bin\Win32` and `.\bin\x64`
|
||||
|
||||
### Windows (Test Project)
|
||||
1. Include the main StormLib header: `#include <StormLib.h>`
|
||||
2. Set the correct library directory for StormLibXYZ.lib:
|
||||
* X: D = Debug, R = Release
|
||||
* Y: A = ANSI build, U = Unicode build
|
||||
* Z: S = Using static CRT library, D = Using Dynamic CRT library
|
||||
3. Rebuild
|
||||
78
vendor/stormlib-9/doc/History.txt
vendored
Normal file
78
vendor/stormlib-9/doc/History.txt
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
StormLib history
|
||||
================
|
||||
|
||||
Version 9.11
|
||||
|
||||
- Fixed bug in processing HET table.
|
||||
|
||||
Version 9.10
|
||||
|
||||
- Support for weak-signing
|
||||
- Anti-protector: New Spazzler
|
||||
|
||||
Version 9.00
|
||||
|
||||
- Support for streaming (master-mirror)
|
||||
- Support for multi-file MPQs used by some WoW versions
|
||||
- Opening maps protected by Spazzler protector
|
||||
- Opening maps protected by BOBA protector
|
||||
|
||||
Version 8.02
|
||||
|
||||
- Support for UNICODE encoding for on-disk files
|
||||
- Optimized file deleting
|
||||
|
||||
Version 8.01
|
||||
|
||||
- SFileFindFirstFile and SFileFindNextFile no longer find files that have
|
||||
patch file in the oldest MPQ in the patch chain
|
||||
- Write support for MPQs version 4
|
||||
|
||||
Version 8.00
|
||||
|
||||
- Updated support for protected maps from Warcraft III
|
||||
|
||||
Version 7.11
|
||||
|
||||
- Support for MPQs v 3.0 (WOW-Cataclysm BETA)
|
||||
- StormLib now deals properly with files that have MPQ_SECTOR_CHECKSUM missing,
|
||||
but have sector checksum entry present in the sector offset table
|
||||
|
||||
Version 7.10
|
||||
|
||||
- Support for partial MPQs ("interface.MPQ.part")
|
||||
- The only operation that is externally allowed to do with internal files
|
||||
("(listfile)", "(attributes)" and "(signature)") is reading. Attempt to modify any of the file
|
||||
fails and GetLastError returns ERROR_INTERNAL_FILE
|
||||
- Fixed memory leak that has occured when writing more than one sector to the file at once
|
||||
|
||||
Version 7.01
|
||||
|
||||
- Support for adding files from memory
|
||||
- Fixed improper validation of handles to MPQ file and MPQ archive
|
||||
- Fixed bug where StormLib didn't save CRC32 of the file when added to archive
|
||||
|
||||
Version 7.00
|
||||
|
||||
- Properly deals with MPQs protected by w3xMaster
|
||||
- Major rewrite
|
||||
- Fixed support for (attributes)
|
||||
- Added file verification
|
||||
- Added MPQ signature verification
|
||||
|
||||
Version 6.22
|
||||
|
||||
- Properly deals with MPQs protected by w3xMaster
|
||||
|
||||
Version 6.21
|
||||
|
||||
- SFileRenameFile now properly re-crypts the file if necessary.
|
||||
- SFileFindFirstFile correctly deals with deleted files
|
||||
|
||||
Version 6.20
|
||||
|
||||
- Fixed lots of bugs when processing files with same names but different locales
|
||||
- Fixed bugs when repeately extracts the same file with MPQ_FILE_SINGLE_UNIT flag
|
||||
- Added SFileFlushArchive
|
||||
- Fixed issue opening AVI files renamed to MPQ using SFileCreateArchiveEx
|
||||
318
vendor/stormlib-9/doc/The MoPaQ File Format 0.9.txt
vendored
Normal file
318
vendor/stormlib-9/doc/The MoPaQ File Format 0.9.txt
vendored
Normal file
@ -0,0 +1,318 @@
|
||||
THE MOPAQ ARCHIVE FORMAT
|
||||
v0.9 (Thursday, June 30, 2005)
|
||||
by Justin Olbrantz(Quantam)
|
||||
|
||||
Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting
|
||||
in other works is freely allowed, as long as the source and author of the quote is stated.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
1. Introduction to the MoPaQ Format
|
||||
2. The MoPaQ Format
|
||||
2.1 General Archive Layout
|
||||
2.2 Archive Header
|
||||
2.3 Block Table
|
||||
2.4 Hash Table
|
||||
2.5 File Data
|
||||
2.6 Listfile
|
||||
2.7 Extended Attributes
|
||||
2.8 Weak (Old) Digital Signature
|
||||
2.9 Strong (New) Digital Signature
|
||||
3. Algorithm Source Code
|
||||
3.1 Encryption/Decryption
|
||||
3.2 Hashing
|
||||
3.3 Conversion of FILETIME and time_t
|
||||
|
||||
1. INTRODUCTION TO THE MOPAQ FORMAT
|
||||
The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard
|
||||
Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be
|
||||
a read-only game archive format, and excels at this role.
|
||||
|
||||
The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked.
|
||||
The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
|
||||
|
||||
2. THE MOPAQ FORMAT
|
||||
All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified),
|
||||
byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise.
|
||||
Structure members are listed in the following general form:
|
||||
offset from the beginning of the structure: data type(array size) member name : member description
|
||||
|
||||
2.1 GENERAL ARCHIVE LAYOUT
|
||||
- Archive Header
|
||||
- File Data
|
||||
- File Data - Special Files
|
||||
- Hash Table
|
||||
- Block Table
|
||||
- Strong Digital signature
|
||||
|
||||
This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table
|
||||
and file table after the archive header, and before the file data.
|
||||
|
||||
2.2 ARCHIVE HEADER
|
||||
00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
|
||||
04h: int32 HeaderSize : Size of the archive header. Should be 32.
|
||||
08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present.
|
||||
This size is used, among other things, for determining the region to hash in computing the digital signature.
|
||||
0Ch: int16 Unknown : Unknown
|
||||
0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
|
||||
in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate
|
||||
that this should always be 3 (4096 byte sectors).
|
||||
10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16.
|
||||
1Ch: int32 BlockTableEntries : Number of entries in the block table.
|
||||
|
||||
The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset
|
||||
0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not
|
||||
at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the
|
||||
archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer
|
||||
versions (due to the strong digital signature not being considered a part of the archive).
|
||||
|
||||
2.3 BLOCK TABLE
|
||||
The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be
|
||||
overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash
|
||||
of "(block table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0.
|
||||
04h: int32 BlockSize : Size of the block in the archive.
|
||||
08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
|
||||
0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
|
||||
80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared.
|
||||
01000000h: File is stored as a single unit, rather than split into sectors.
|
||||
00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
|
||||
00010000h: File is encrypted.
|
||||
00000200h: File is compressed. Mutually exclusive to file imploded.
|
||||
00000100h: File is imploded. Mutually exclusive to file compressed.
|
||||
|
||||
2.4 HASH TABLE
|
||||
Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 FilePathHashA : The hash of the file path, using method A.
|
||||
04h: int32 FilePathHashB : The hash of the file path, using method B.
|
||||
08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
|
||||
0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
|
||||
FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
|
||||
FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
|
||||
|
||||
2.5 FILE DATA
|
||||
00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below).
|
||||
immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below).
|
||||
|
||||
Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize).
|
||||
|
||||
If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib.
|
||||
40h: IMA ADPCM mono
|
||||
80h: IMA ADPCM stereo
|
||||
01h: Huffman encoded
|
||||
02h: Deflated (see ZLib)
|
||||
08h: Imploded (see PKWare Data Compression Library)
|
||||
10h: BZip2 compressed (see BZip2)
|
||||
|
||||
If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which
|
||||
contains the entire file.
|
||||
|
||||
If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable)
|
||||
is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the
|
||||
directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is
|
||||
adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset)
|
||||
XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions,
|
||||
by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the
|
||||
0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
|
||||
|
||||
The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize.
|
||||
This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors
|
||||
is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the
|
||||
SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously.
|
||||
Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as
|
||||
a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the
|
||||
archive's sector size).
|
||||
|
||||
2.6 LISTFILE
|
||||
The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive.
|
||||
The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)",
|
||||
and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file
|
||||
"(listfile)" may not be listed in the listfile.
|
||||
|
||||
2.7 EXTENDED ATTRIBUTES
|
||||
The extended attributes are optional file attributes for files in the block table. These attributes were added at times after
|
||||
the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes.
|
||||
If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although
|
||||
the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the
|
||||
blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file,
|
||||
in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other
|
||||
structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some
|
||||
archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This
|
||||
file is structured as follows:
|
||||
|
||||
00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
|
||||
04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
|
||||
00000001h: File CRC32s.
|
||||
00000002h: File timestamps.
|
||||
00000004h: File MD5s.
|
||||
08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the
|
||||
archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block
|
||||
in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
|
||||
immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive.
|
||||
Omitted if the archive does not have MD5s.
|
||||
|
||||
2.8 WEAK DIGITAL SIGNATURE
|
||||
The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5
|
||||
digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this
|
||||
protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature
|
||||
is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the
|
||||
archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature
|
||||
file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during
|
||||
signing/verification. This file is structured as follows:
|
||||
|
||||
00h: int32 Unknown : Must be 0.
|
||||
04h: int32 Unknown : must be 0.
|
||||
08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order.
|
||||
|
||||
2.9 STRONG DIGITAL SIGNATURE
|
||||
The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and
|
||||
a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well.
|
||||
The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize
|
||||
bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
|
||||
|
||||
00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
|
||||
04h: int2048 Signature : The digital signature, stored in little-endian format.
|
||||
|
||||
When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows:
|
||||
|
||||
00h: byte Padding : Must be 0Bh.
|
||||
01h: byte(235) Padding : Must be BBh.
|
||||
ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format.
|
||||
|
||||
3. ALGORITHM SOURCE CODE
|
||||
3.1 ENCRYPTION/DECRYPTION
|
||||
I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order.
|
||||
|
||||
unsigned long dwCryptTable[0x500];
|
||||
|
||||
void InitializeCryptTable()
|
||||
{
|
||||
unsigned long seed = 0x00100001;
|
||||
unsigned long index1 = 0;
|
||||
unsigned long index2 = 0;
|
||||
int i;
|
||||
|
||||
for (index1 = 0; index1 < 0x100; index1++)
|
||||
{
|
||||
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
|
||||
{
|
||||
unsigned long temp1, temp2;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp1 = (seed & 0xFFFF) << 0x10;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp2 = (seed & 0xFFFF);
|
||||
|
||||
dwCryptTable[index2] = (temp1 | temp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
assert(lpbyBuffer);
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = *lpdwBuffer + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
assert(lpbyBuffer);
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = ch + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
3.2 HASHING
|
||||
Based on code from StormLib.
|
||||
|
||||
// Different types of hashes to make with HashString
|
||||
#define MPQ_HASH_TABLE_OFFSET 0
|
||||
#define MPQ_HASH_NAME_A 1
|
||||
#define MPQ_HASH_NAME_B 2
|
||||
#define MPQ_HASH_FILE_KEY 3
|
||||
|
||||
unsigned long HashString(const char *lpszString, unsigned long dwHashType)
|
||||
{
|
||||
unsigned long seed1 = 0x7FED7FED;
|
||||
unsigned long seed2 = 0xEEEEEEEE;
|
||||
int ch;
|
||||
|
||||
while (*lpszString != 0)
|
||||
{
|
||||
ch = toupper(*lpszString++);
|
||||
|
||||
seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2);
|
||||
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
|
||||
}
|
||||
return seed1;
|
||||
}
|
||||
|
||||
3.3 CONVERSION OF FILETIME AND time_t
|
||||
|
||||
#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
|
||||
|
||||
bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time)
|
||||
{
|
||||
// The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
|
||||
unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
|
||||
|
||||
if (nTime < EPOCH_OFFSET)
|
||||
return false;
|
||||
|
||||
nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
|
||||
nTime /= 10000000ULL; // Convert 100 ns to sec
|
||||
|
||||
time = (time_t)nTime;
|
||||
|
||||
// Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
|
||||
if ((nTime - (unsigned long long)time) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetFileTimeFromTime(time_t &time, FILETIME &fileTime)
|
||||
{
|
||||
unsigned long long nTime = (unsigned long long)time;
|
||||
|
||||
nTime *= 10000000ULL;
|
||||
nTime += EPOCH_OFFSET;
|
||||
|
||||
fileTime.dwLowDateTime = (DWORD)nTime;
|
||||
fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
|
||||
}
|
||||
433
vendor/stormlib-9/doc/The MoPaQ File Format 1.0.txt
vendored
Normal file
433
vendor/stormlib-9/doc/The MoPaQ File Format 1.0.txt
vendored
Normal file
@ -0,0 +1,433 @@
|
||||
THE MOPAQ ARCHIVE FORMAT
|
||||
v1.0 (Friday, September 1, 2006)
|
||||
by Justin Olbrantz(Quantam)
|
||||
|
||||
Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quotation in other works is freely allowed, as long as the source and author of the quote are stated.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
1. Introduction to the MoPaQ Format
|
||||
2. The MoPaQ Format
|
||||
2.1 General Archive Layout
|
||||
2.2 Archive Header
|
||||
2.3 Block Table
|
||||
2.4 Extended Block Table
|
||||
2.5 Hash Table
|
||||
2.6 File Data
|
||||
2.7 Listfile
|
||||
2.8 Extended Attributes
|
||||
2.9 Weak (Old) Digital Signature
|
||||
2.10 Strong (New) Digital Signature
|
||||
3. Algorithm Source Code
|
||||
3.1 Encryption/Decryption
|
||||
3.2 Hashing and File Key Computation
|
||||
3.3 Finding Files
|
||||
3.4 Deleting Files
|
||||
3.5 Conversion of FILETIME and time_t
|
||||
3.6 Forming a 64-bit Large Archive Offset from 32-bit and 16-bit Components
|
||||
4. Revision History
|
||||
|
||||
1. INTRODUCTION TO THE MOPAQ FORMAT
|
||||
The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be a read-only game archive format, and excels at this role.
|
||||
|
||||
The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
|
||||
|
||||
StormLib - mentioned several times in this specification - is an open-source MoPaQ reading and writing library written by Ladislav Zezula (no affiliation with Blizzard Entertainment). While it's a bit dated, and does not support all of the newer MoPaQ features, it contains source code to the more exotic compression methods used by MoPaQ, such as the PKWare implode algorithm, MoPaQ's huffman compression algorithm, and the IMA ADPCM compression used by MoPaQ.
|
||||
|
||||
2. THE MOPAQ FORMAT
|
||||
All numbers in the MoPaQ format are in little endian byte order; signed numbers use the two's complement system. Data types are listed either as int (integer, the number of bits specified), byte (8 bits), or char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. Structure members are listed in the following general form:
|
||||
offset from the beginning of the structure: data type(array size) member name : member description
|
||||
|
||||
2.1 GENERAL ARCHIVE LAYOUT
|
||||
- Archive Header
|
||||
- File Data
|
||||
- File Data - Special Files
|
||||
- Hash Table
|
||||
- Block Table
|
||||
- Extended Block Table
|
||||
- Strong Digital signature
|
||||
|
||||
This is the usual archive format, but it is not mandatory. Some archives have been observed placing the hash table and file table after the archive header, and before the file data.
|
||||
|
||||
2.2 ARCHIVE HEADER
|
||||
00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
|
||||
04h: int32 HeaderSize : Size of the archive header.
|
||||
08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. This size is used, among other things, for determining the region to hash in computing the digital signature. This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive is calculated as the size from the beginning of the archive to the end of the hash table, block table, or extended block table (whichever is largest).
|
||||
0Ch: int16 FormatVersion : MoPaQ format version. MPQAPI will not open archives where this is negative. Known versions:
|
||||
0000h: Original format. HeaderSize should be 20h, and large archives are not supported.
|
||||
0001h: Burning Crusade format. Header size should be 2Ch, and large archives are supported.
|
||||
0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors).
|
||||
10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
||||
1Ch: int32 BlockTableEntries : Number of entries in the block table.
|
||||
Fields only present in the Burning Crusade format and later:
|
||||
20h: int64 ExtendedBlockTableOffset : Offset to the beginning of the extended block table, relative to the beginning of the archive.
|
||||
28h: int16 HashTableOffsetHigh : High 16 bits of the hash table offset for large archives.
|
||||
2Ah: int16 BlockTableOffsetHigh : High 16 bits of the block table offset for large archives.
|
||||
|
||||
The archive header is the first structure in the archive, at archive offset 0; however, the archive does not need to be at offset 0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer versions (due to the strong digital signature not being considered a part of the archive).
|
||||
|
||||
2.3 BLOCK TABLE
|
||||
The block table contains entries for each region in the archive. Regions may be either files, empty space, which may be overwritten by new files (typically this space is from deleted file data), or unused block table entries. Empty space entries should have BlockOffset and BlockSize nonzero, and FileSize and Flags zero; unused block table entries should have BlockSize, FileSize, and Flags zero. The block table is encrypted, using the hash of "(block table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive.
|
||||
04h: int32 BlockSize : Size of the block in the archive.
|
||||
08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file; otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
|
||||
0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
|
||||
80000000h: Block is a file, and follows the file data format; otherwise, block is free space or unused. If the block is not a file, all other flags should be cleared, and FileSize should be 0.
|
||||
01000000h: File is stored as a single unit, rather than split into sectors.
|
||||
00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
|
||||
00010000h: File is encrypted.
|
||||
00000200h: File is compressed. File cannot be imploded.
|
||||
00000100h: File is imploded. File cannot be compressed.
|
||||
|
||||
2.4 EXTENDED BLOCK TABLE
|
||||
The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes). The table contains the upper bits of the archive offsets for each block in the block table. It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block, with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size.
|
||||
|
||||
As of the Burning Crusade Friends and Family beta, this table is not encrypted.
|
||||
|
||||
2.5 HASH TABLE
|
||||
Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 FilePathHashA : The hash of the file path, using method A.
|
||||
04h: int32 FilePathHashB : The hash of the file path, using method B.
|
||||
08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
|
||||
0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
|
||||
FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
|
||||
FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
|
||||
|
||||
2.6 FILE DATA
|
||||
The data for each file is composed of the following structure:
|
||||
00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector, relative to the beginning of the file data. The last entry contains the file size, making it possible to easily calculate the size of any given sector. This table is not present if this information can be calculated (see details below).
|
||||
immediately following SectorOffsetTable: SECTOR Sectors(SectorsInFile) : Data of each sector in the file, packed end to end (see details below).
|
||||
|
||||
Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may contain less than this, depending on the size of the entire file's data. If the file is compressed or imploded, the sector will be smaller or the same size as the file data it contains. Individual sectors in a compressed or imploded file may be stored uncompressed; this occurs if and only if the file data the sector contains could not be compressed by the algorithm(s) used (if the compressed sector size was greater than or equal to the size of the file data), and is indicated by the sector's size in SectorOffsetTable being equal to the size of the file data in the sector (which may be calculated from the FileSize).
|
||||
|
||||
The format of each sector depends on the kind of sector it is. Uncompressed sectors are simply the the raw file data contained in the sector. Imploded sectors are the raw compressed data following compression with the implode algorithm (these sectors can only be in imploded files). Compressed sectors (only found in compressed - not imploded - files) are compressed with one or more compression algorithms, and have the following structure:
|
||||
00h: byte CompressionMask : Mask of the compression types applied to this sector. If multiple compression types are used, they are applied in the order listed below, and decompression is performed in the opposite order. This byte counts towards the total sector size, meaning that the sector will be stored uncompressed if the data cannot be compressed by at least two bytes; as well, this byte is encrypted with the sector data, if applicable. The following compression types are defined (for implementations of these algorithms, see StormLib):
|
||||
40h: IMA ADPCM mono
|
||||
80h: IMA ADPCM stereo
|
||||
01h: Huffman encoded
|
||||
02h: Deflated (see ZLib)
|
||||
08h: Imploded (see PKWare Data Compression Library)
|
||||
10h: BZip2 compressed (see BZip2)
|
||||
01h: byte(SectorSize - 1) SectorData : The compressed data for the sector.
|
||||
|
||||
If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which contains the entire file data.
|
||||
|
||||
If the file is encrypted, each sector (after compression/implosion, if applicable) is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) XOR FileSize) (StormLib incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the 0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
|
||||
|
||||
The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. However, the SectorOffsetTable will be present if the file is compressed/imploded and the file is not stored as a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the archive's sector size).
|
||||
|
||||
2.7 LISTFILE
|
||||
The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)" (default language and platform), and is simply a text file with file paths separated by ';', 0Dh, 0Ah, or some combination of these. The file "(listfile)" may not be listed in the listfile.
|
||||
|
||||
2.8 EXTENDED ATTRIBUTES
|
||||
The extended attributes are optional file attributes for files in the block table. These attributes were added at times after the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file (default language and platform), in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This file is structured as follows:
|
||||
|
||||
00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
|
||||
04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
|
||||
00000001h: File CRC32s.
|
||||
00000002h: File timestamps.
|
||||
00000004h: File MD5s.
|
||||
08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have CRC32s.
|
||||
immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
|
||||
immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have MD5s.
|
||||
|
||||
2.9 WEAK DIGITAL SIGNATURE
|
||||
The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation
|
||||
of the RSASSA-PKCS1-v1_5 digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak)
|
||||
RSA key (for more information about this protocol, see the RSA Labs PKCS1 specification). The public key
|
||||
and exponent are stored in a resource in Storm, the private key is stored in a separate file, whose filename
|
||||
is passed to MPQAPI (the private key is not stored in MPQAPI). The signature is stored uncompressed,
|
||||
unencrypted in the file "(signature)" (default language and platform) in the archive. The archive
|
||||
is hashed from the beginning of the archive (ArchiveOffset in the containing file) to the end of
|
||||
the archive (the length indicated by ArchiveSize, or calculated in the Burning Crusade MoPaQ format);
|
||||
the signature file is added to the archive before signing, and the space occupied by the file is considered
|
||||
to be all binary 0s during signing/verification. This file is structured as follows:
|
||||
|
||||
00h: int32 Unknown : Must be 0.
|
||||
04h: int32 Unknown : Must be 0.
|
||||
08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored
|
||||
in little-endian order. The structure of this, when decrypted, follows the RSASSA-PKCS1-v1_5 specification;
|
||||
this format is rather icky to work with (I wrote a program to verify this signature using nothing but an MD5
|
||||
function and huge integer functions; it wasn't pleasant), and best left to an encryption library such as Cryto++.
|
||||
|
||||
2.10 STRONG DIGITAL SIGNATURE
|
||||
The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
|
||||
|
||||
00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
|
||||
04h: int2048 Signature : The digital signature, stored in little-endian format.
|
||||
|
||||
When the Signature field is decrypted with the public key and exponent, and the resulting large integer is stored in little-endian order, it is structured as follows:
|
||||
|
||||
00h: byte Padding : Must be 0Bh.
|
||||
01h: byte(235) Padding : Must be BBh.
|
||||
ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 byte order.
|
||||
|
||||
3. ALGORITHM SOURCE CODE
|
||||
All of the sample code here assumes little endian machine byte order, that the short type is 16 bits, that the long type is 32 bits, and that the long long type is 64 bits. Adjustments must be made if these assumptions are not correct on a given platform. All code not credited otherwise was written by myself in the writing of this specification.
|
||||
|
||||
3.1 ENCRYPTION/DECRYPTION
|
||||
Based on code from StormLib.
|
||||
|
||||
unsigned long dwCryptTable[0x500];
|
||||
|
||||
// The encryption and hashing functions use a number table in their procedures. This table must be initialized before the functions are called the first time.
|
||||
void InitializeCryptTable()
|
||||
{
|
||||
unsigned long seed = 0x00100001;
|
||||
unsigned long index1 = 0;
|
||||
unsigned long index2 = 0;
|
||||
int i;
|
||||
|
||||
for (index1 = 0; index1 < 0x100; index1++)
|
||||
{
|
||||
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
|
||||
{
|
||||
unsigned long temp1, temp2;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp1 = (seed & 0xFFFF) << 0x10;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp2 = (seed & 0xFFFF);
|
||||
|
||||
dwCryptTable[index2] = (temp1 | temp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
assert(lpbyBuffer);
|
||||
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = *lpdwBuffer + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
assert(lpbyBuffer);
|
||||
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEEL;
|
||||
unsigned long ch;
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111L) | (dwKey >> 0x0B);
|
||||
seed = ch + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
3.2 HASHING AND FILE KEY COMPUTATION
|
||||
These functions may have been derived from StormLib code at some point in the very distant past. It was so long ago that I don't remember for certain.
|
||||
|
||||
// Different types of hashes to make with HashString
|
||||
#define MPQ_HASH_TABLE_OFFSET 0
|
||||
#define MPQ_HASH_NAME_A 1
|
||||
#define MPQ_HASH_NAME_B 2
|
||||
#define MPQ_HASH_FILE_KEY 3
|
||||
|
||||
// Based on code from StormLib.
|
||||
unsigned long HashString(const char *lpszString, unsigned long dwHashType)
|
||||
{
|
||||
assert(lpszString);
|
||||
assert(dwHashType <= MPQ_HASH_FILE_KEY);
|
||||
|
||||
unsigned long seed1 = 0x7FED7FEDL;
|
||||
unsigned long seed2 = 0xEEEEEEEEL;
|
||||
int ch;
|
||||
|
||||
while (*lpszString != 0)
|
||||
{
|
||||
ch = toupper(*lpszString++);
|
||||
|
||||
seed1 = dwCryptTable[(dwHashType * 0x100) + ch] ^ (seed1 + seed2);
|
||||
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
|
||||
}
|
||||
return seed1;
|
||||
}
|
||||
|
||||
#define BLOCK_OFFSET_ADJUSTED_KEY 0x00020000L
|
||||
|
||||
unsigned long ComputeFileKey(const char *lpszFilePath, const BlockTableEntry &blockEntry, unsigned long nArchiveOffset)
|
||||
{
|
||||
assert(lpszFilePath);
|
||||
|
||||
// Find the file name part of the path
|
||||
const char *lpszFileName = strrchr(lpszFilePath, '\\');
|
||||
if (lpszFileName)
|
||||
lpszFileName++; // Skip the \
|
||||
else
|
||||
lpszFileName = lpszFilePath;
|
||||
|
||||
// Hash the name to get the base key
|
||||
unsigned long nFileKey = HashString(lpszFileName, MPQ_HASH_FILE_KEY);
|
||||
|
||||
// Offset-adjust the key if necessary
|
||||
if (blockEntry.Flags & BLOCK_OFFSET_ADJUSTED_KEY)
|
||||
nFileKey = (nFileKey + blockEntry.BlockOffset) ^ blockEntry.FileSize;
|
||||
|
||||
return nFileKey;
|
||||
}
|
||||
|
||||
3.3 FINDING FILES
|
||||
|
||||
#define MPQ_HASH_ENTRY_EMPTY 0xFFFFFFFFL
|
||||
#define MPQ_HASH_ENTRY_DELETED 0xFFFFFFFEL
|
||||
|
||||
bool FindFileInHashTable(const HashTableEntry *lpHashTable, unsigned long nHashTableSize, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform, unsigned long &iFileHashEntry)
|
||||
{
|
||||
assert(lpHashTable);
|
||||
assert(nHashTableSize);
|
||||
assert(lpszFilePath);
|
||||
|
||||
// Find the home entry in the hash table for the file
|
||||
unsigned long iInitEntry = HashString(lpszFilePath, MPQ_HASH_TABLE_OFFSET) & (nHashTableSize - 1);
|
||||
|
||||
// Is there anything there at all?
|
||||
if (lpHashTable[iInitEntry].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
|
||||
return false;
|
||||
|
||||
// Compute the hashes to compare the hash table entry against
|
||||
unsigned long nNameHashA = HashString(lpszFilePath, MPQ_HASH_NAME_A),
|
||||
nNameHashB = HashString(lpszFilePath, MPQ_HASH_NAME_B),
|
||||
iCurEntry = iInitEntry;
|
||||
|
||||
// Check each entry in the hash table till a termination point is reached
|
||||
do
|
||||
{
|
||||
if (lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_DELETED)
|
||||
{
|
||||
if (lpHashTable[iCurEntry].FilePathHashA == nNameHashA
|
||||
&& lpHashTable[iCurEntry].FilePathHashB == nNameHashB
|
||||
&& lpHashTable[iCurEntry].Language == nLang
|
||||
&& lpHashTable[iCurEntry].Platform == nPlatform)
|
||||
{
|
||||
iFileHashEntry = iCurEntry;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
iCurEntry = (iCurEntry + 1) & (nHashTableSize - 1);
|
||||
} while (iCurEntry != iInitEntry && lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_EMPTY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
3.4 DELETING FILES
|
||||
|
||||
bool DeleteFile(HashTableEntry *lpHashTable, unsigned long nHashTableSize, BlockTableEntry *lpBlockTable, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform)
|
||||
{
|
||||
assert(lpHashTable);
|
||||
assert(nHashTableSize);
|
||||
assert(lpBlockTable);
|
||||
|
||||
// Find the file in the hash table
|
||||
unsigned long iFileHashEntry;
|
||||
|
||||
if (!FindFileInHashTable(lpHashTable, nHashTableSize, lpszFilePath, nLang, nPlatform, iFileHashEntry))
|
||||
return false;
|
||||
|
||||
// Get the block table index before we nuke the hash table entry
|
||||
unsigned long iFileBlockEntry = lpHashTable[iFileHashEntry].FileBlockIndex;
|
||||
|
||||
// Delete the file's entry in the hash table
|
||||
memset(&lpHashTable[iFileHashEntry], 0xFF, sizeof(HashTableEntry));
|
||||
|
||||
// If the next entry is empty, mark this one as empty; otherwise, mark this as deleted.
|
||||
if (lpHashTable[(iFileHashEntry + 1) & (nHashTableSize - 1)].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
|
||||
lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_EMPTY;
|
||||
else
|
||||
lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_DELETED;
|
||||
|
||||
// If the block occupies space, mark the block as free space; otherwise, clear the block table entry.
|
||||
if (lpBlockTable[iFileBlockEntry].BlockSize > 0)
|
||||
{
|
||||
lpBlockTable[iFileBlockEntry].FileSize = 0;
|
||||
lpBlockTable[iFileBlockEntry].Flags = 0;
|
||||
}
|
||||
else
|
||||
memset(&lpBlockTable[iFileBlockEntry], 0, sizeof(BlockTableEntry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
3.5 CONVERSION OF FILETIME AND time_t
|
||||
This code assumes that the base ("zero") date for time_t is 01/01/1970. This is true on Windows, Unix System V systems, and Mac OS X. It is unknown whether this is true on all other platforms. You'll need to research this yourself, if you plan on porting it somewhere else.
|
||||
|
||||
#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
|
||||
|
||||
bool GetTimeFromFileTime(const FILETIME &fileTime, time_t &time)
|
||||
{
|
||||
// The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
|
||||
unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
|
||||
|
||||
if (nTime < EPOCH_OFFSET)
|
||||
return false;
|
||||
|
||||
nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
|
||||
nTime /= 10000000ULL; // Convert 100 ns to sec
|
||||
|
||||
time = (time_t)nTime;
|
||||
|
||||
// Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
|
||||
if ((nTime - (unsigned long long)time) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetFileTimeFromTime(const time_t &time, FILETIME &fileTime)
|
||||
{
|
||||
unsigned long long nTime = (unsigned long long)time;
|
||||
|
||||
nTime *= 10000000ULL;
|
||||
nTime += EPOCH_OFFSET;
|
||||
|
||||
fileTime.dwLowDateTime = (DWORD)nTime;
|
||||
fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
|
||||
}
|
||||
|
||||
3.6 FORMING A 64-BIT LARGE ARCHIVE OFFSET FROM 32-BIT AND 16-BIT COMPONENTS
|
||||
unsigned long long MakeLargeArchiveOffset(unsigned long nOffsetLow, unsigned short nOffsetHigh)
|
||||
{
|
||||
return ((unsigned long long)nOffsetHigh << 32) + (unsigned long long)nOffsetLow;
|
||||
}
|
||||
|
||||
4. REVISION HISTORY
|
||||
1.0
|
||||
- Updated to include most of the changes found in the Burning Crusade Friends and Family beta
|
||||
|
||||
0.91.
|
||||
- Updated several structure member descriptions
|
||||
- Listed the full set of characters that can separate list file entries
|
||||
- Noted that (attributes), (listfile), and (signature) use the default language and platform codes
|
||||
- Redid part of the file data specs to clarify the format of sectors
|
||||
- Enhanced descriptions of the different kinds of block table entries
|
||||
- Added ComputeFileKey, FindFileInHashTable, and DeleteFile source
|
||||
24
vendor/stormlib-9/src/DllMain.c
vendored
Normal file
24
vendor/stormlib-9/src/DllMain.c
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/*****************************************************************************/
|
||||
/* DllMain.c Copyright (c) Ladislav Zezula 2006 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: DllMain for the StormLib.dll library */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 23.11.06 1.00 Lad The first version of DllMain.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DllMain
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hInst);
|
||||
UNREFERENCED_PARAMETER(dwReason);
|
||||
UNREFERENCED_PARAMETER(lpReserved);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
79
vendor/stormlib-9/src/DllMain.def
vendored
Normal file
79
vendor/stormlib-9/src/DllMain.def
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
;
|
||||
; Export file for Windows
|
||||
; Copyright (c) 2007-2010 Ladislav Zezula
|
||||
; ladik@zezula.net
|
||||
;
|
||||
|
||||
LIBRARY StormLib.dll
|
||||
|
||||
EXPORTS
|
||||
|
||||
SFileSetLocale
|
||||
SFileGetLocale
|
||||
|
||||
SFileOpenArchive
|
||||
SFileCreateArchive
|
||||
SFileCreateArchive2
|
||||
SFileFlushArchive
|
||||
SFileCloseArchive
|
||||
|
||||
SFileAddListFile
|
||||
|
||||
SFileSetCompactCallback
|
||||
SFileCompactArchive
|
||||
|
||||
SFileGetMaxFileCount
|
||||
SFileSetMaxFileCount
|
||||
|
||||
SFileGetAttributes
|
||||
SFileSetAttributes
|
||||
SFileUpdateFileAttributes
|
||||
|
||||
SFileOpenPatchArchive
|
||||
SFileIsPatchedArchive
|
||||
|
||||
SFileOpenFileEx
|
||||
SFileGetFileSize
|
||||
SFileSetFilePointer
|
||||
SFileReadFile
|
||||
SFileCloseFile
|
||||
|
||||
SFileHasFile
|
||||
SFileGetFileName
|
||||
SFileGetFileInfo
|
||||
|
||||
SFileExtractFile
|
||||
|
||||
SFileVerifyFile
|
||||
SFileVerifyRawData
|
||||
SFileVerifyArchive
|
||||
|
||||
SFileFindFirstFile
|
||||
SFileFindNextFile
|
||||
SFileFindClose
|
||||
|
||||
SListFileFindFirstFile
|
||||
SListFileFindNextFile
|
||||
SListFileFindClose
|
||||
|
||||
SFileEnumLocales
|
||||
|
||||
SFileCreateFile
|
||||
SFileWriteFile
|
||||
SFileFinishFile
|
||||
SFileAddFileEx
|
||||
SFileAddFile
|
||||
SFileAddWave
|
||||
SFileRemoveFile
|
||||
SFileRenameFile
|
||||
SFileSetFileLocale
|
||||
SFileSetDataCompression
|
||||
SFileSetAddFileCallback
|
||||
|
||||
SCompImplode
|
||||
SCompExplode
|
||||
SCompCompress
|
||||
SCompDecompress
|
||||
|
||||
GetLastError=Kernel32.GetLastError
|
||||
SetLastError=Kernel32.SetLastError
|
||||
110
vendor/stormlib-9/src/DllMain.rc
vendored
Normal file
110
vendor/stormlib-9/src/DllMain.rc
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1250)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 9,25,0,3
|
||||
PRODUCTVERSION 9,25,0,3
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x0L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040504b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "http://www.zezula.net/mpq.html"
|
||||
VALUE "FileDescription", "StormLib library for reading Blizzard MPQ archives"
|
||||
VALUE "FileVersion", "9.25.0.3"
|
||||
VALUE "InternalName", "StormLib"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2014 - 2023 Ladislav Zezula"
|
||||
VALUE "OriginalFilename", "StormLib.dll"
|
||||
VALUE "ProductName", "StormLib"
|
||||
VALUE "ProductVersion", "9.25.0.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x405, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Czech (Czech Republic) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY)
|
||||
LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
|
||||
#pragma code_page(1250)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Czech (Czech Republic) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
2928
vendor/stormlib-9/src/FileStream.cpp
vendored
Normal file
2928
vendor/stormlib-9/src/FileStream.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
217
vendor/stormlib-9/src/FileStream.h
vendored
Normal file
217
vendor/stormlib-9/src/FileStream.h
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/*****************************************************************************/
|
||||
/* FileStream.h Copyright (c) Ladislav Zezula 2012 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: Definitions for FileStream object */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 14.04.12 1.00 Lad The first version of FileStream.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __FILESTREAM_H__
|
||||
#define __FILESTREAM_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Function prototypes
|
||||
|
||||
typedef void (*STREAM_INIT)(
|
||||
struct TFileStream * pStream // Pointer to an unopened stream
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_CREATE)(
|
||||
struct TFileStream * pStream // Pointer to an unopened stream
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_OPEN)(
|
||||
struct TFileStream * pStream, // Pointer to an unopened stream
|
||||
const TCHAR * szFileName, // Pointer to file name to be open
|
||||
DWORD dwStreamFlags // Stream flags
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_READ)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
||||
void * pvBuffer, // Pointer to data to be read
|
||||
DWORD dwBytesToRead // Number of bytes to read from the file
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_WRITE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position
|
||||
const void * pvBuffer, // Pointer to data to be written
|
||||
DWORD dwBytesToWrite // Number of bytes to read from the file
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_RESIZE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG FileSize // New size for the file, in bytes
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_GETSIZE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pFileSize // Receives the file size, in bytes
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_GETPOS)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pByteOffset // Pointer to store current file position
|
||||
);
|
||||
|
||||
typedef void (*STREAM_CLOSE)(
|
||||
struct TFileStream * pStream // Pointer to an open stream
|
||||
);
|
||||
|
||||
typedef bool (*BLOCK_READ)(
|
||||
struct TFileStream * pStream, // Pointer to a block-oriented stream
|
||||
ULONGLONG StartOffset, // Byte offset of start of the block array
|
||||
ULONGLONG EndOffset, // End offset (either end of the block or end of the file)
|
||||
LPBYTE BlockBuffer, // Pointer to block-aligned buffer
|
||||
DWORD BytesNeeded, // Number of bytes that are really needed
|
||||
bool bAvailable // true if the block is available
|
||||
);
|
||||
|
||||
typedef bool (*BLOCK_CHECK)(
|
||||
struct TFileStream * pStream, // Pointer to a block-oriented stream
|
||||
ULONGLONG BlockOffset // Offset of the file to check
|
||||
);
|
||||
|
||||
typedef void (*BLOCK_SAVEMAP)(
|
||||
struct TFileStream * pStream // Pointer to a block-oriented stream
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures - partial file structure and bitmap footer
|
||||
|
||||
#define ID_FILE_BITMAP_FOOTER 0x33767470 // Signature of the file bitmap footer ('ptv3')
|
||||
#define DEFAULT_BLOCK_SIZE 0x00004000 // Default size of the stream block
|
||||
#define DEFAULT_BUILD_NUMBER 10958 // Build number for newly created partial MPQs
|
||||
|
||||
typedef struct _PART_FILE_HEADER
|
||||
{
|
||||
DWORD PartialVersion; // Always set to 2
|
||||
char GameBuildNumber[0x20]; // Minimum build number of the game that can use this MPQ
|
||||
DWORD Flags; // Flags (details unknown)
|
||||
DWORD FileSizeLo; // Low 32 bits of the contained file size
|
||||
DWORD FileSizeHi; // High 32 bits of the contained file size
|
||||
DWORD BlockSize; // Size of one file block, in bytes
|
||||
|
||||
} PART_FILE_HEADER, *PPART_FILE_HEADER;
|
||||
|
||||
// Structure describing the block-to-file map entry
|
||||
typedef struct _PART_FILE_MAP_ENTRY
|
||||
{
|
||||
DWORD Flags; // 3 = the block is present in the file
|
||||
DWORD BlockOffsLo; // Low 32 bits of the block position in the file
|
||||
DWORD BlockOffsHi; // High 32 bits of the block position in the file
|
||||
DWORD LargeValueLo; // 64-bit value, meaning is unknown
|
||||
DWORD LargeValueHi;
|
||||
|
||||
} PART_FILE_MAP_ENTRY, *PPART_FILE_MAP_ENTRY;
|
||||
|
||||
typedef struct _FILE_BITMAP_FOOTER
|
||||
{
|
||||
DWORD Signature; // 'ptv3' (ID_FILE_BITMAP_FOOTER)
|
||||
DWORD Version; // Unknown, seems to always have value of 3 (version?)
|
||||
DWORD BuildNumber; // Game build number for that MPQ
|
||||
DWORD MapOffsetLo; // Low 32-bits of the offset of the bit map
|
||||
DWORD MapOffsetHi; // High 32-bits of the offset of the bit map
|
||||
DWORD BlockSize; // Size of one block (usually 0x4000 bytes)
|
||||
|
||||
} FILE_BITMAP_FOOTER, *PFILE_BITMAP_FOOTER;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structure for file stream
|
||||
|
||||
union TBaseProviderData
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONGLONG FileSize; // Size of the file
|
||||
ULONGLONG FilePos; // Current file position
|
||||
ULONGLONG FileTime; // Last write time
|
||||
HANDLE hFile; // File handle
|
||||
} File;
|
||||
|
||||
struct
|
||||
{
|
||||
ULONGLONG FileSize; // Size of the file
|
||||
ULONGLONG FilePos; // Current file position
|
||||
ULONGLONG FileTime; // Last write time
|
||||
LPBYTE pbFile; // Pointer to mapped view
|
||||
} Map;
|
||||
|
||||
struct
|
||||
{
|
||||
ULONGLONG FileSize; // Size of the file
|
||||
ULONGLONG FilePos; // Current file position
|
||||
ULONGLONG FileTime; // Last write time
|
||||
HANDLE hInternet; // Internet handle
|
||||
HANDLE hConnect; // Connection to the internet server
|
||||
} Http;
|
||||
};
|
||||
|
||||
struct TFileStream
|
||||
{
|
||||
// Stream provider functions
|
||||
STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly.
|
||||
STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly.
|
||||
STREAM_RESIZE StreamResize; // Pointer to function changing file size
|
||||
STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size
|
||||
STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position
|
||||
STREAM_CLOSE StreamClose; // Pointer to function closing the stream
|
||||
|
||||
// Block-oriented functions
|
||||
BLOCK_READ BlockRead; // Pointer to function reading one or more blocks
|
||||
BLOCK_CHECK BlockCheck; // Pointer to function checking whether the block is present
|
||||
|
||||
// Base provider functions
|
||||
STREAM_CREATE BaseCreate; // Pointer to base create function
|
||||
STREAM_OPEN BaseOpen; // Pointer to base open function
|
||||
STREAM_READ BaseRead; // Read from the stream
|
||||
STREAM_WRITE BaseWrite; // Write to the stream
|
||||
STREAM_RESIZE BaseResize; // Pointer to function changing file size
|
||||
STREAM_GETSIZE BaseGetSize; // Pointer to function returning file size
|
||||
STREAM_GETPOS BaseGetPos; // Pointer to function that returns current file position
|
||||
STREAM_CLOSE BaseClose; // Pointer to function closing the stream
|
||||
|
||||
// Base provider data (file size, file position)
|
||||
TBaseProviderData Base;
|
||||
|
||||
// Stream provider data
|
||||
TFileStream * pMaster; // Master stream (e.g. MPQ on a web server)
|
||||
TCHAR * szFileName; // File name (self-relative pointer)
|
||||
|
||||
ULONGLONG StreamSize; // Stream size (can be less than file size)
|
||||
ULONGLONG StreamPos; // Stream position
|
||||
DWORD BuildNumber; // Game build number
|
||||
DWORD dwFlags; // Stream flags
|
||||
|
||||
// Followed by stream provider data, with variable length
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures for block-oriented stream
|
||||
|
||||
struct TBlockStream : public TFileStream
|
||||
{
|
||||
SFILE_DOWNLOAD_CALLBACK pfnCallback; // Callback for downloading
|
||||
void * FileBitmap; // Array of bits for file blocks
|
||||
void * UserData; // User data to be passed to the download callback
|
||||
DWORD BitmapSize; // Size of the file bitmap (in bytes)
|
||||
DWORD BlockSize; // Size of one block, in bytes
|
||||
DWORD BlockCount; // Number of data blocks in the file
|
||||
DWORD IsComplete; // If nonzero, no blocks are missing
|
||||
DWORD IsModified; // nonzero if the bitmap has been modified
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structure for encrypted stream
|
||||
|
||||
#define MPQE_CHUNK_SIZE 0x40 // Size of one chunk to be decrypted
|
||||
|
||||
struct TEncryptedStream : public TBlockStream
|
||||
{
|
||||
BYTE Key[MPQE_CHUNK_SIZE]; // File key
|
||||
};
|
||||
|
||||
#endif // __FILESTREAM_H__
|
||||
85
vendor/stormlib-9/src/LibTomCrypt.c
vendored
Normal file
85
vendor/stormlib-9/src/LibTomCrypt.c
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// This compound source is here for reducing the long build time
|
||||
// of the entire StormLib library
|
||||
//
|
||||
|
||||
#pragma warning(disable:4242) // der_decode_ia5_string.c(84) : warning C4242: '=' : conversion from 'int' to 'unsigned char', possible loss of data
|
||||
|
||||
#include "libtomcrypt/src/hashes/hash_memory.c"
|
||||
#include "libtomcrypt/src/hashes/md5.c"
|
||||
#include "libtomcrypt/src/hashes/sha1.c"
|
||||
#include "libtomcrypt/src/hashes/sha256.c"
|
||||
#include "libtomcrypt/src/math/multi.c"
|
||||
#include "libtomcrypt/src/math/rand_prime.c"
|
||||
#include "libtomcrypt/src/misc/base64_decode.c"
|
||||
#include "libtomcrypt/src/misc/crypt_argchk.c"
|
||||
#include "libtomcrypt/src/misc/crypt_find_hash.c"
|
||||
#include "libtomcrypt/src/misc/crypt_find_prng.c"
|
||||
#include "libtomcrypt/src/misc/crypt_hash_descriptor.c"
|
||||
#include "libtomcrypt/src/misc/crypt_hash_is_valid.c"
|
||||
#include "libtomcrypt/src/misc/crypt_libc.c"
|
||||
#include "libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c"
|
||||
#include "libtomcrypt/src/misc/crypt_prng_descriptor.c"
|
||||
#include "libtomcrypt/src/misc/crypt_prng_is_valid.c"
|
||||
#include "libtomcrypt/src/misc/crypt_register_hash.c"
|
||||
#include "libtomcrypt/src/misc/crypt_register_prng.c"
|
||||
#include "libtomcrypt/src/misc/zeromem.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_bit_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_boolean.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_choice.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_ia5_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_object_identifier.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_octet_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_printable_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_short_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_utctime.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_decode_utf8_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_bit_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_boolean.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_ia5_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_object_identifier.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_octet_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_printable_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_set.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_setof.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_short_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_utctime.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_encode_utf8_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_bit_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_boolean.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_ia5_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_object_identifier.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_octet_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_printable_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_sequence.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_short_integer.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_utctime.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_length_utf8_string.c"
|
||||
#include "libtomcrypt/src/pk/asn1/der_sequence_free.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_map.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_points.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c"
|
||||
#include "libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c"
|
||||
#include "libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_exptmod.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_free.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_import.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_make_key.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_sign_hash.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_verify_hash.c"
|
||||
#include "libtomcrypt/src/pk/rsa/rsa_verify_simple.c"
|
||||
125
vendor/stormlib-9/src/LibTomMath.c
vendored
Normal file
125
vendor/stormlib-9/src/LibTomMath.c
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// This compound source is here for reducing the long build time
|
||||
// of the entire StormLib library
|
||||
//
|
||||
|
||||
#pragma warning(disable:4334) // warning C4334: '<<' : result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
|
||||
|
||||
#include "libtommath/bn_fast_mp_invmod.c"
|
||||
#include "libtommath/bn_fast_mp_montgomery_reduce.c"
|
||||
#include "libtommath/bn_fast_s_mp_mul_digs.c"
|
||||
#include "libtommath/bn_fast_s_mp_mul_high_digs.c"
|
||||
#include "libtommath/bn_fast_s_mp_sqr.c"
|
||||
#include "libtommath/bn_mp_2expt.c"
|
||||
#include "libtommath/bn_mp_abs.c"
|
||||
#include "libtommath/bn_mp_add.c"
|
||||
#include "libtommath/bn_mp_add_d.c"
|
||||
#include "libtommath/bn_mp_addmod.c"
|
||||
#include "libtommath/bn_mp_and.c"
|
||||
#include "libtommath/bn_mp_clamp.c"
|
||||
#include "libtommath/bn_mp_clear.c"
|
||||
#include "libtommath/bn_mp_clear_multi.c"
|
||||
#include "libtommath/bn_mp_cmp.c"
|
||||
#include "libtommath/bn_mp_cmp_d.c"
|
||||
#include "libtommath/bn_mp_cmp_mag.c"
|
||||
#include "libtommath/bn_mp_cnt_lsb.c"
|
||||
#include "libtommath/bn_mp_copy.c"
|
||||
#include "libtommath/bn_mp_count_bits.c"
|
||||
#include "libtommath/bn_mp_div.c"
|
||||
#include "libtommath/bn_mp_div_2.c"
|
||||
#include "libtommath/bn_mp_div_2d.c"
|
||||
#include "libtommath/bn_mp_div_3.c"
|
||||
#include "libtommath/bn_mp_div_d.c"
|
||||
#include "libtommath/bn_mp_dr_is_modulus.c"
|
||||
#include "libtommath/bn_mp_dr_reduce.c"
|
||||
#include "libtommath/bn_mp_dr_setup.c"
|
||||
#include "libtommath/bn_mp_exch.c"
|
||||
#include "libtommath/bn_mp_expt_d.c"
|
||||
#include "libtommath/bn_mp_exptmod.c"
|
||||
#include "libtommath/bn_mp_exptmod_fast.c"
|
||||
#include "libtommath/bn_mp_exteuclid.c"
|
||||
#include "libtommath/bn_mp_fread.c"
|
||||
#include "libtommath/bn_mp_fwrite.c"
|
||||
#include "libtommath/bn_mp_gcd.c"
|
||||
#include "libtommath/bn_mp_get_int.c"
|
||||
#include "libtommath/bn_mp_grow.c"
|
||||
#include "libtommath/bn_mp_init.c"
|
||||
#include "libtommath/bn_mp_init_copy.c"
|
||||
#include "libtommath/bn_mp_init_multi.c"
|
||||
#include "libtommath/bn_mp_init_set.c"
|
||||
#include "libtommath/bn_mp_init_set_int.c"
|
||||
#include "libtommath/bn_mp_init_size.c"
|
||||
#include "libtommath/bn_mp_invmod.c"
|
||||
#include "libtommath/bn_mp_invmod_slow.c"
|
||||
#include "libtommath/bn_mp_is_square.c"
|
||||
#include "libtommath/bn_mp_jacobi.c"
|
||||
#include "libtommath/bn_mp_karatsuba_mul.c"
|
||||
#include "libtommath/bn_mp_karatsuba_sqr.c"
|
||||
#include "libtommath/bn_mp_lcm.c"
|
||||
#include "libtommath/bn_mp_lshd.c"
|
||||
#include "libtommath/bn_mp_mod.c"
|
||||
#include "libtommath/bn_mp_mod_2d.c"
|
||||
#include "libtommath/bn_mp_mod_d.c"
|
||||
#include "libtommath/bn_mp_montgomery_calc_normalization.c"
|
||||
#include "libtommath/bn_mp_montgomery_reduce.c"
|
||||
#include "libtommath/bn_mp_montgomery_setup.c"
|
||||
#include "libtommath/bn_mp_mul.c"
|
||||
#include "libtommath/bn_mp_mul_2.c"
|
||||
#include "libtommath/bn_mp_mul_2d.c"
|
||||
#include "libtommath/bn_mp_mul_d.c"
|
||||
#include "libtommath/bn_mp_mulmod.c"
|
||||
#include "libtommath/bn_mp_n_root.c"
|
||||
#include "libtommath/bn_mp_neg.c"
|
||||
#include "libtommath/bn_mp_or.c"
|
||||
#include "libtommath/bn_mp_prime_fermat.c"
|
||||
#include "libtommath/bn_mp_prime_is_divisible.c"
|
||||
#include "libtommath/bn_mp_prime_is_prime.c"
|
||||
#include "libtommath/bn_mp_prime_miller_rabin.c"
|
||||
#include "libtommath/bn_mp_prime_next_prime.c"
|
||||
#include "libtommath/bn_mp_prime_rabin_miller_trials.c"
|
||||
#include "libtommath/bn_mp_prime_random_ex.c"
|
||||
#include "libtommath/bn_mp_radix_size.c"
|
||||
#include "libtommath/bn_mp_radix_smap.c"
|
||||
#include "libtommath/bn_mp_rand.c"
|
||||
#include "libtommath/bn_mp_read_radix.c"
|
||||
#include "libtommath/bn_mp_read_signed_bin.c"
|
||||
#include "libtommath/bn_mp_read_unsigned_bin.c"
|
||||
#include "libtommath/bn_mp_reduce.c"
|
||||
#include "libtommath/bn_mp_reduce_2k.c"
|
||||
#include "libtommath/bn_mp_reduce_2k_l.c"
|
||||
#include "libtommath/bn_mp_reduce_2k_setup.c"
|
||||
#include "libtommath/bn_mp_reduce_2k_setup_l.c"
|
||||
#include "libtommath/bn_mp_reduce_is_2k.c"
|
||||
#include "libtommath/bn_mp_reduce_is_2k_l.c"
|
||||
#include "libtommath/bn_mp_reduce_setup.c"
|
||||
#include "libtommath/bn_mp_rshd.c"
|
||||
#include "libtommath/bn_mp_set.c"
|
||||
#include "libtommath/bn_mp_set_int.c"
|
||||
#include "libtommath/bn_mp_shrink.c"
|
||||
#include "libtommath/bn_mp_signed_bin_size.c"
|
||||
#include "libtommath/bn_mp_sqr.c"
|
||||
#include "libtommath/bn_mp_sqrmod.c"
|
||||
#include "libtommath/bn_mp_sqrt.c"
|
||||
#include "libtommath/bn_mp_sub.c"
|
||||
#include "libtommath/bn_mp_sub_d.c"
|
||||
#include "libtommath/bn_mp_submod.c"
|
||||
#include "libtommath/bn_mp_to_signed_bin.c"
|
||||
#include "libtommath/bn_mp_to_signed_bin_n.c"
|
||||
#include "libtommath/bn_mp_to_unsigned_bin.c"
|
||||
#include "libtommath/bn_mp_to_unsigned_bin_n.c"
|
||||
#include "libtommath/bn_mp_toom_mul.c"
|
||||
#include "libtommath/bn_mp_toom_sqr.c"
|
||||
#include "libtommath/bn_mp_toradix.c"
|
||||
#include "libtommath/bn_mp_toradix_n.c"
|
||||
#include "libtommath/bn_mp_unsigned_bin_size.c"
|
||||
#include "libtommath/bn_mp_xor.c"
|
||||
#include "libtommath/bn_mp_zero.c"
|
||||
#include "libtommath/bn_prime_tab.c"
|
||||
#include "libtommath/bn_reverse.c"
|
||||
#include "libtommath/bn_s_mp_add.c"
|
||||
#include "libtommath/bn_s_mp_exptmod.c"
|
||||
#include "libtommath/bn_s_mp_mul_digs.c"
|
||||
#include "libtommath/bn_s_mp_mul_high_digs.c"
|
||||
#include "libtommath/bn_s_mp_sqr.c"
|
||||
#include "libtommath/bn_s_mp_sub.c"
|
||||
#include "libtommath/bncore.c"
|
||||
4
vendor/stormlib-9/src/LibTomMathDesc.c
vendored
Normal file
4
vendor/stormlib-9/src/LibTomMathDesc.c
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// This is a source file for WDK build of StormLib
|
||||
// It is copied to the root folder during the build process
|
||||
|
||||
#include "libtomcrypt/src/math/ltm_desc.c"
|
||||
1974
vendor/stormlib-9/src/SBaseCommon.cpp
vendored
Normal file
1974
vendor/stormlib-9/src/SBaseCommon.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
183
vendor/stormlib-9/src/SBaseDumpData.cpp
vendored
Normal file
183
vendor/stormlib-9/src/SBaseDumpData.cpp
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
/*****************************************************************************/
|
||||
/* SBaseDumpData.cpp Copyright (c) Ladislav Zezula 2011 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 26.01.11 1.00 Lad The first version of SBaseDumpData.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
#ifdef __STORMLIB_DUMP_DATA__
|
||||
|
||||
void DumpMpqHeader(TMPQHeader * pHeader)
|
||||
{
|
||||
printf("== MPQ Header =================================\n");
|
||||
printf("DWORD dwID = %08X\n", pHeader->dwID);
|
||||
printf("DWORD dwHeaderSize = %08X\n", pHeader->dwHeaderSize);
|
||||
printf("DWORD dwArchiveSize = %08X\n", pHeader->dwArchiveSize);
|
||||
printf("USHORT wFormatVersion = %04X\n", pHeader->wFormatVersion);
|
||||
printf("USHORT wSectorSize = %04X\n", pHeader->wSectorSize);
|
||||
printf("DWORD dwHashTablePos = %08X\n", pHeader->dwHashTablePos);
|
||||
printf("DWORD dwBlockTablePos = %08X\n", pHeader->dwBlockTablePos);
|
||||
printf("DWORD dwHashTableSize = %08X\n", pHeader->dwHashTableSize);
|
||||
printf("DWORD dwBlockTableSize = %08X\n", pHeader->dwBlockTableSize);
|
||||
printf("ULONGLONG HiBlockTablePos64 = %016llX\n", pHeader->HiBlockTablePos64);
|
||||
printf("USHORT wHashTablePosHi = %04X\n", pHeader->wHashTablePosHi);
|
||||
printf("USHORT wBlockTablePosHi = %04X\n", pHeader->wBlockTablePosHi);
|
||||
printf("ULONGLONG ArchiveSize64 = %016llX\n", pHeader->ArchiveSize64);
|
||||
printf("ULONGLONG BetTablePos64 = %016llX\n", pHeader->BetTablePos64);
|
||||
printf("ULONGLONG HetTablePos64 = %016llX\n", pHeader->HetTablePos64);
|
||||
printf("ULONGLONG HashTableSize64 = %016llX\n", pHeader->HashTableSize64);
|
||||
printf("ULONGLONG BlockTableSize64 = %016llX\n", pHeader->BlockTableSize64);
|
||||
printf("ULONGLONG HiBlockTableSize64 = %016llX\n", pHeader->HiBlockTableSize64);
|
||||
printf("ULONGLONG HetTableSize64 = %016llX\n", pHeader->HetTableSize64);
|
||||
printf("ULONGLONG BetTableSize64 = %016llX\n", pHeader->BetTableSize64);
|
||||
printf("DWORD dwRawChunkSize = %08X\n", pHeader->dwRawChunkSize);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
void DumpHashTable(TMPQHash * pHashTable, DWORD dwHashTableSize)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if(pHashTable == NULL || dwHashTableSize == 0)
|
||||
return;
|
||||
|
||||
printf("== Hash Table =================================\n");
|
||||
for(i = 0; i < dwHashTableSize; i++)
|
||||
{
|
||||
printf("[%08x] %08X %08X %04X %02X %08X\n", i,
|
||||
pHashTable[i].dwName1,
|
||||
pHashTable[i].dwName2,
|
||||
pHashTable[i].Locale,
|
||||
pHashTable[i].Platform,
|
||||
pHashTable[i].dwBlockIndex);
|
||||
}
|
||||
printf("-----------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if(pHetTable == NULL || pBetTable == NULL)
|
||||
return;
|
||||
|
||||
printf("== HET Header =================================\n");
|
||||
printf("ULONGLONG AndMask64 = %016llX\n", pHetTable->AndMask64);
|
||||
printf("ULONGLONG OrMask64 = %016llX\n", pHetTable->OrMask64);
|
||||
printf("DWORD dwEntryCount = %08X\n", pHetTable->dwEntryCount);
|
||||
printf("DWORD dwTotalCount = %08X\n", pHetTable->dwTotalCount);
|
||||
printf("DWORD dwNameHashBitSize = %08X\n", pHetTable->dwNameHashBitSize);
|
||||
printf("DWORD dwIndexSizeTotal = %08X\n", pHetTable->dwIndexSizeTotal);
|
||||
printf("DWORD dwIndexSizeExtra = %08X\n", pHetTable->dwIndexSizeExtra);
|
||||
printf("DWORD dwIndexSize = %08X\n", pHetTable->dwIndexSize);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
|
||||
printf("== BET Header =================================\n");
|
||||
printf("DWORD dwTableEntrySize = %08X\n", pBetTable->dwTableEntrySize);
|
||||
printf("DWORD dwBitIndex_FilePos = %08X\n", pBetTable->dwBitIndex_FilePos);
|
||||
printf("DWORD dwBitIndex_FileSize = %08X\n", pBetTable->dwBitIndex_FileSize);
|
||||
printf("DWORD dwBitIndex_CmpSize = %08X\n", pBetTable->dwBitIndex_CmpSize);
|
||||
printf("DWORD dwBitIndex_FlagIndex = %08X\n", pBetTable->dwBitIndex_FlagIndex);
|
||||
printf("DWORD dwBitIndex_Unknown = %08X\n", pBetTable->dwBitIndex_Unknown);
|
||||
printf("DWORD dwBitCount_FilePos = %08X\n", pBetTable->dwBitCount_FilePos);
|
||||
printf("DWORD dwBitCount_FileSize = %08X\n", pBetTable->dwBitCount_FileSize);
|
||||
printf("DWORD dwBitCount_CmpSize = %08X\n", pBetTable->dwBitCount_CmpSize);
|
||||
printf("DWORD dwBitCount_FlagIndex = %08X\n", pBetTable->dwBitCount_FlagIndex);
|
||||
printf("DWORD dwBitCount_Unknown = %08X\n", pBetTable->dwBitCount_Unknown);
|
||||
printf("DWORD dwBitTotal_NameHash2 = %08X\n", pBetTable->dwBitTotal_NameHash2);
|
||||
printf("DWORD dwBitExtra_NameHash2 = %08X\n", pBetTable->dwBitExtra_NameHash2);
|
||||
printf("DWORD dwBitCount_NameHash2 = %08X\n", pBetTable->dwBitCount_NameHash2);
|
||||
printf("DWORD dwEntryCount = %08X\n", pBetTable->dwEntryCount);
|
||||
printf("DWORD dwFlagCount = %08X\n", pBetTable->dwFlagCount);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
|
||||
printf("== HET & Bet Table ======================================================================\n\n");
|
||||
printf("HetIdx HetHash BetIdx BetHash ByteOffset FileSize CmpSize FlgIdx Flags \n");
|
||||
printf("------ ------- ------ ---------------- ---------------- -------- -------- ------ --------\n");
|
||||
for(i = 0; i < pHetTable->dwTotalCount; i++)
|
||||
{
|
||||
ULONGLONG ByteOffset = 0;
|
||||
ULONGLONG BetHash = 0;
|
||||
DWORD dwFileSize = 0;
|
||||
DWORD dwCmpSize = 0;
|
||||
DWORD dwFlagIndex = 0;
|
||||
DWORD dwFlags = 0;
|
||||
DWORD dwBetIndex = 0;
|
||||
|
||||
GetMPQBits(pHetTable->pBetIndexes, i * pHetTable->dwIndexSizeTotal,
|
||||
pHetTable->dwIndexSize,
|
||||
&dwBetIndex, 4);
|
||||
|
||||
if(dwBetIndex < pHetTable->dwTotalCount)
|
||||
{
|
||||
DWORD dwEntryIndex = pBetTable->dwTableEntrySize * dwBetIndex;
|
||||
|
||||
GetMPQBits(pBetTable->pNameHashes, dwBetIndex * pBetTable->dwBitTotal_NameHash2,
|
||||
pBetTable->dwBitCount_NameHash2,
|
||||
&BetHash, 8);
|
||||
|
||||
GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FilePos,
|
||||
pBetTable->dwBitCount_FilePos,
|
||||
&ByteOffset, 8);
|
||||
|
||||
GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FileSize,
|
||||
pBetTable->dwBitCount_FileSize,
|
||||
&dwFileSize, 4);
|
||||
|
||||
GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_CmpSize,
|
||||
pBetTable->dwBitCount_CmpSize,
|
||||
&dwCmpSize, 4);
|
||||
|
||||
GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FlagIndex,
|
||||
pBetTable->dwBitCount_FlagIndex,
|
||||
&dwFlagIndex, 4);
|
||||
|
||||
dwFlags = pBetTable->pFileFlags[dwFlagIndex];
|
||||
}
|
||||
|
||||
printf(" %04X %02lX %04X %016llX %016llX %08X %08X %04X %08X\n", i,
|
||||
pHetTable->pNameHashes[i],
|
||||
dwBetIndex,
|
||||
BetHash,
|
||||
ByteOffset,
|
||||
dwFileSize,
|
||||
dwCmpSize,
|
||||
dwFlagIndex,
|
||||
dwFlags);
|
||||
}
|
||||
printf("-----------------------------------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
void DumpFileTable(TFileEntry * pFileTable, DWORD dwFileTableSize)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if(pFileTable == NULL || dwFileTableSize == 0)
|
||||
return;
|
||||
|
||||
printf("== File Table =================================\n");
|
||||
for(i = 0; i < dwFileTableSize; i++, pFileTable++)
|
||||
{
|
||||
printf("[%04u] %08X-%08X %08X-%08X %08X-%08X 0x%08X 0x%08X 0x%08X %s\n", i,
|
||||
(DWORD)(pFileTable->FileNameHash >> 0x20),
|
||||
(DWORD)(pFileTable->FileNameHash & 0xFFFFFFFF),
|
||||
(DWORD)(pFileTable->ByteOffset >> 0x20),
|
||||
(DWORD)(pFileTable->ByteOffset & 0xFFFFFFFF),
|
||||
(DWORD)(pFileTable->FileTime >> 0x20),
|
||||
(DWORD)(pFileTable->FileTime & 0xFFFFFFFF),
|
||||
pFileTable->dwFileSize,
|
||||
pFileTable->dwCmpSize,
|
||||
pFileTable->dwFlags,
|
||||
pFileTable->szFileName != NULL ? pFileTable->szFileName : "");
|
||||
}
|
||||
printf("-----------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
#endif // __STORMLIB_DUMP_DATA__
|
||||
3120
vendor/stormlib-9/src/SBaseFileTable.cpp
vendored
Normal file
3120
vendor/stormlib-9/src/SBaseFileTable.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
688
vendor/stormlib-9/src/SBaseSubTypes.cpp
vendored
Normal file
688
vendor/stormlib-9/src/SBaseSubTypes.cpp
vendored
Normal file
@ -0,0 +1,688 @@
|
||||
/*****************************************************************************/
|
||||
/* SBaseSubTypes.cpp Copyright (c) Ladislav Zezula 2013 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Conversion routines for archive formats that are similar to MPQ format */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 02.11.11 1.00 Lad The first version of SBaseSubTypes.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Support for SQP file format (War of the Immortals) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _TSQPHeader
|
||||
{
|
||||
// The ID_MPQ ('MPQ\x1A') signature
|
||||
DWORD dwID;
|
||||
|
||||
// Size of the archive header
|
||||
DWORD dwHeaderSize;
|
||||
|
||||
// 32-bit size of MPQ archive
|
||||
DWORD dwArchiveSize;
|
||||
|
||||
// Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
DWORD dwHashTablePos;
|
||||
|
||||
// Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
DWORD dwBlockTablePos;
|
||||
|
||||
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
|
||||
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
||||
DWORD dwHashTableSize;
|
||||
|
||||
// Number of entries in the block table
|
||||
DWORD dwBlockTableSize;
|
||||
|
||||
// Must be zero for SQP files
|
||||
USHORT wFormatVersion;
|
||||
|
||||
// Power of two exponent specifying the number of 512-byte disk sectors in each file sector
|
||||
// in the archive. The size of each file sector in the archive is 512 * 2 ^ wSectorSize.
|
||||
USHORT wSectorSize;
|
||||
|
||||
} TSQPHeader;
|
||||
|
||||
typedef struct _TSQPHash
|
||||
{
|
||||
// Most likely the Locale + Platform
|
||||
DWORD dwAlwaysZero;
|
||||
|
||||
// If the hash table entry is valid, this is the index into the block table of the file.
|
||||
// Otherwise, one of the following two values:
|
||||
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
|
||||
// Terminates searches for a given file.
|
||||
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
|
||||
// Does not terminate searches for a given file.
|
||||
DWORD dwBlockIndex;
|
||||
|
||||
// The hash of the file path, using method A.
|
||||
DWORD dwName1;
|
||||
|
||||
// The hash of the file path, using method B.
|
||||
DWORD dwName2;
|
||||
|
||||
} TSQPHash;
|
||||
|
||||
typedef struct _TSQPBlock
|
||||
{
|
||||
// Offset of the beginning of the file, relative to the beginning of the archive.
|
||||
DWORD dwFilePos;
|
||||
|
||||
// Flags for the file. See MPQ_FILE_XXXX constants
|
||||
DWORD dwFlags;
|
||||
|
||||
// Compressed file size
|
||||
DWORD dwCSize;
|
||||
|
||||
// Uncompressed file size
|
||||
DWORD dwFSize;
|
||||
|
||||
} TSQPBlock;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions - SQP file format
|
||||
|
||||
// This function converts SQP file header into MPQ file header
|
||||
DWORD ConvertSqpHeaderToFormat4(
|
||||
TMPQArchive * ha,
|
||||
ULONGLONG FileSize,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
TSQPHeader * pSqpHeader = (TSQPHeader *)ha->HeaderData;
|
||||
TMPQHeader Header;
|
||||
|
||||
// SQP files from War of the Immortal use MPQ file format with slightly
|
||||
// modified structure. These fields have different position:
|
||||
//
|
||||
// Offset TMPQHeader TSQPHeader
|
||||
// ------ ---------- -----------
|
||||
// 000C wFormatVersion dwHashTablePos (lo)
|
||||
// 000E wSectorSize dwHashTablePos (hi)
|
||||
// 001C dwBlockTableSize (lo) wBlockSize
|
||||
// 001E dwHashTableSize (hi) wFormatVersion
|
||||
|
||||
// Can't open the archive with certain flags
|
||||
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
// The file must not be greater than 4 GB
|
||||
if((FileSize >> 0x20) != 0)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
// Translate the SQP header into a MPQ header
|
||||
memset(&Header, 0, sizeof(TMPQHeader));
|
||||
Header.dwID = BSWAP_INT32_UNSIGNED(pSqpHeader->dwID);
|
||||
Header.dwHeaderSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHeaderSize);
|
||||
Header.dwArchiveSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwArchiveSize);
|
||||
Header.dwHashTablePos = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHashTablePos);
|
||||
Header.dwBlockTablePos = BSWAP_INT32_UNSIGNED(pSqpHeader->dwBlockTablePos);
|
||||
Header.dwHashTableSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwHashTableSize);
|
||||
Header.dwBlockTableSize = BSWAP_INT32_UNSIGNED(pSqpHeader->dwBlockTableSize);
|
||||
Header.wFormatVersion = BSWAP_INT16_UNSIGNED(pSqpHeader->wFormatVersion);
|
||||
Header.wSectorSize = BSWAP_INT16_UNSIGNED(pSqpHeader->wSectorSize);
|
||||
|
||||
// Verify the SQP header
|
||||
if(Header.dwID == g_dwMpqSignature && Header.dwHeaderSize == sizeof(TSQPHeader) && Header.dwArchiveSize == FileSize)
|
||||
{
|
||||
// Check for fixed values of version and sector size
|
||||
if(Header.wFormatVersion == MPQ_FORMAT_VERSION_1 && Header.wSectorSize == 3)
|
||||
{
|
||||
// Initialize the fields of 3.0 header
|
||||
Header.ArchiveSize64 = Header.dwArchiveSize;
|
||||
Header.HashTableSize64 = Header.dwHashTableSize * sizeof(TMPQHash);
|
||||
Header.BlockTableSize64 = Header.dwBlockTableSize * sizeof(TMPQBlock);
|
||||
|
||||
// Copy the converted MPQ header back
|
||||
memcpy(ha->HeaderData, &Header, sizeof(TMPQHeader));
|
||||
|
||||
// Mark this file as SQP file
|
||||
ha->pfnHashString = HashStringSlash;
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
ha->dwSubType = MPQ_SUBTYPE_SQP;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
void * LoadSqpTable(TMPQArchive * ha, DWORD dwByteOffset, DWORD cbTableSize, DWORD dwKey)
|
||||
{
|
||||
ULONGLONG ByteOffset;
|
||||
LPBYTE pbSqpTable;
|
||||
|
||||
// Allocate buffer for the table
|
||||
pbSqpTable = STORM_ALLOC(BYTE, cbTableSize);
|
||||
if(pbSqpTable != NULL)
|
||||
{
|
||||
// Load the table
|
||||
ByteOffset = ha->MpqPos + dwByteOffset;
|
||||
if(FileStream_Read(ha->pStream, &ByteOffset, pbSqpTable, cbTableSize))
|
||||
{
|
||||
// Decrypt the SQP table
|
||||
DecryptMpqBlock(pbSqpTable, cbTableSize, dwKey);
|
||||
return pbSqpTable;
|
||||
}
|
||||
|
||||
// Free the table
|
||||
STORM_FREE(pbSqpTable);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TSQPHash * pSqpHashTable;
|
||||
TSQPHash * pSqpHashEnd;
|
||||
TSQPHash * pSqpHash;
|
||||
TMPQHash * pMpqHash;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Load the hash table
|
||||
pSqpHashTable = (TSQPHash *)LoadSqpTable(ha, pHeader->dwHashTablePos, pHeader->dwHashTableSize * sizeof(TSQPHash), MPQ_KEY_HASH_TABLE);
|
||||
if(pSqpHashTable != NULL)
|
||||
{
|
||||
// Parse the entire hash table and convert it to MPQ hash table
|
||||
pSqpHashEnd = pSqpHashTable + pHeader->dwHashTableSize;
|
||||
pMpqHash = (TMPQHash *)pSqpHashTable;
|
||||
for(pSqpHash = pSqpHashTable; pSqpHash < pSqpHashEnd; pSqpHash++, pMpqHash++)
|
||||
{
|
||||
// Ignore free entries
|
||||
if(pSqpHash->dwBlockIndex != HASH_ENTRY_FREE)
|
||||
{
|
||||
// Store the hash entry to a temporary variable
|
||||
TSQPHash TempEntry = *pSqpHash;
|
||||
|
||||
// Check block index against the size of the block table
|
||||
if(pHeader->dwBlockTableSize <= MPQ_BLOCK_INDEX(pSqpHash) && pSqpHash->dwBlockIndex < HASH_ENTRY_DELETED)
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
|
||||
// We do not support nonzero locale and platform ID
|
||||
if(pSqpHash->dwAlwaysZero != 0 && pSqpHash->dwAlwaysZero != HASH_ENTRY_FREE)
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Copy the entry to the MPQ hash entry
|
||||
pMpqHash->dwName1 = TempEntry.dwName1;
|
||||
pMpqHash->dwName2 = TempEntry.dwName2;
|
||||
pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(&TempEntry);
|
||||
pMpqHash->Locale = 0;
|
||||
pMpqHash->Platform = 0;
|
||||
pMpqHash->Reserved = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If an error occured, we need to free the hash table
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
STORM_FREE(pSqpHashTable);
|
||||
pSqpHashTable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the converted hash table (or NULL on failure)
|
||||
return (TMPQHash *)pSqpHashTable;
|
||||
}
|
||||
|
||||
// Loads the SQP Block table and converts it to a MPQ block table
|
||||
TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TSQPBlock * pSqpBlockTable;
|
||||
TSQPBlock * pSqpBlockEnd;
|
||||
TSQPBlock * pSqpBlock;
|
||||
TMPQBlock * pMpqBlock;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Load the hash table
|
||||
pSqpBlockTable = (TSQPBlock *)LoadSqpTable(ha, pHeader->dwBlockTablePos, pHeader->dwBlockTableSize * sizeof(TSQPBlock), MPQ_KEY_BLOCK_TABLE);
|
||||
if(pSqpBlockTable != NULL)
|
||||
{
|
||||
// Parse the entire hash table and convert it to MPQ hash table
|
||||
pSqpBlockEnd = pSqpBlockTable + pHeader->dwBlockTableSize;
|
||||
pMpqBlock = (TMPQBlock *)pSqpBlockTable;
|
||||
for(pSqpBlock = pSqpBlockTable; pSqpBlock < pSqpBlockEnd; pSqpBlock++, pMpqBlock++)
|
||||
{
|
||||
// Store the block entry to a temporary variable
|
||||
TSQPBlock TempEntry = *pSqpBlock;
|
||||
|
||||
// Check for valid flags
|
||||
if(pSqpBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS)
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Convert SQP block table entry to MPQ block table entry
|
||||
pMpqBlock->dwFilePos = TempEntry.dwFilePos;
|
||||
pMpqBlock->dwCSize = TempEntry.dwCSize;
|
||||
pMpqBlock->dwFSize = TempEntry.dwFSize;
|
||||
pMpqBlock->dwFlags = TempEntry.dwFlags;
|
||||
}
|
||||
|
||||
// If an error occured, we need to free the hash table
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
STORM_FREE(pSqpBlockTable);
|
||||
pSqpBlockTable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the converted hash table (or NULL on failure)
|
||||
return (TMPQBlock *)pSqpBlockTable;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Support for MPK file format (Longwu Online) */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define MPK_BLOCK_TABLE_LONGWU 0x86364E6D // MPK table ID for Longwu Online
|
||||
#define MPK_BLOCK_TABLE_WOTGV 0x6d4e3686 // MPK table ID for Warriors of the Ghost Valley
|
||||
|
||||
#define MPK_FILE_UNKNOWN_0001 0x00000001 // Seems to be always present
|
||||
#define MPK_FILE_UNKNOWN_0010 0x00000010 // Seems to be always present
|
||||
#define MPK_FILE_COMPRESSED 0x00000100 // Indicates a compressed file
|
||||
#define MPK_FILE_ENCRYPTED 0x00002000 // Indicates an encrypted file
|
||||
#define MPK_FILE_EXISTS 0x01000000 // Seems to be always present
|
||||
|
||||
typedef struct _TMPKHeader
|
||||
{
|
||||
// The ID_MPK ('MPK\x1A') signature
|
||||
DWORD dwID;
|
||||
|
||||
// Contains '2000'
|
||||
DWORD dwVersion;
|
||||
|
||||
// 32-bit size of the archive
|
||||
DWORD dwArchiveSize;
|
||||
|
||||
// Size of the archive header
|
||||
DWORD dwHeaderSize;
|
||||
|
||||
DWORD dwHashTablePos;
|
||||
DWORD dwHashTableSize;
|
||||
DWORD dwBlockTablePos;
|
||||
DWORD dwBlockTableSize;
|
||||
DWORD dwUnknownPos;
|
||||
DWORD dwUnknownSize;
|
||||
} TMPKHeader;
|
||||
|
||||
|
||||
typedef struct _TMPKHash
|
||||
{
|
||||
// The hash of the file path, using method A.
|
||||
DWORD dwName1;
|
||||
|
||||
// The hash of the file path, using method B.
|
||||
DWORD dwName2;
|
||||
|
||||
// The hash of the file path, using method C.
|
||||
DWORD dwName3;
|
||||
|
||||
// If the hash table entry is valid, this is the index into the block table of the file.
|
||||
// Otherwise, one of the following two values:
|
||||
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
|
||||
// Terminates searches for a given file.
|
||||
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
|
||||
// Does not terminate searches for a given file.
|
||||
DWORD dwBlockIndex;
|
||||
|
||||
} TMPKHash;
|
||||
|
||||
// MPK block for Longwu Online
|
||||
struct TMPKBlock1
|
||||
{
|
||||
DWORD dwFlags; // 0x1121 - Compressed , 0x1120 - Not compressed
|
||||
DWORD dwFilePos; // Offset of the beginning of the file, relative to the beginning of the archive.
|
||||
DWORD dwFSize; // Uncompressed file size
|
||||
DWORD dwCSize; // Compressed file size
|
||||
DWORD dwMagic; // 0x86364E6D for Longwu Online
|
||||
};
|
||||
|
||||
// MPK block for Warriors of the Ghost Valley
|
||||
struct TMPKBlock2
|
||||
{
|
||||
DWORD dwFlags; // 0x1121 - Compressed , 0x1120 - Not compressed
|
||||
DWORD dwFilePos; // Offset of the beginning of the file, relative to the beginning of the archive.
|
||||
DWORD dwFSize; // Uncompressed file size
|
||||
DWORD dwCSize; // Compressed file size
|
||||
DWORD dwMagic; // 0x6d4e3686
|
||||
DWORD dwFlags1; // Unknown
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local variables - MPK file format
|
||||
|
||||
static const unsigned char MpkDecryptionKey[512] =
|
||||
{
|
||||
0x60, 0x20, 0x29, 0xE1, 0x01, 0xCE, 0xAA, 0xFE, 0xA3, 0xAB, 0x8E, 0x30, 0xAF, 0x02, 0xD1, 0x7D,
|
||||
0x41, 0x24, 0x06, 0xBD, 0xAE, 0xBE, 0x43, 0xC3, 0xBA, 0xB7, 0x08, 0x13, 0x51, 0xCF, 0xF8, 0xF7,
|
||||
0x25, 0x42, 0xA5, 0x4A, 0xDA, 0x0F, 0x52, 0x1C, 0x90, 0x3B, 0x63, 0x49, 0x36, 0xF6, 0xDD, 0x1B,
|
||||
0xEA, 0x58, 0xD4, 0x40, 0x70, 0x61, 0x55, 0x09, 0xCD, 0x0B, 0xA2, 0x4B, 0x68, 0x2C, 0x8A, 0xF1,
|
||||
0x3C, 0x3A, 0x65, 0xBB, 0xA1, 0xA8, 0x23, 0x97, 0xFD, 0x15, 0x00, 0x94, 0x88, 0x33, 0x59, 0xE9,
|
||||
0xFB, 0x69, 0x21, 0xEF, 0x85, 0x5B, 0x57, 0x6C, 0xFA, 0xB5, 0xEE, 0xB8, 0x71, 0xDC, 0xB1, 0x38,
|
||||
0x0C, 0x0A, 0x5C, 0x56, 0xC9, 0xB4, 0x84, 0x17, 0x1E, 0xE5, 0xD3, 0x5A, 0xCC, 0xFC, 0x11, 0x86,
|
||||
0x7F, 0x45, 0x4F, 0x54, 0xC8, 0x8D, 0x73, 0x89, 0x79, 0x5D, 0xB3, 0xBF, 0xB9, 0xE3, 0x93, 0xE4,
|
||||
0x6F, 0x35, 0x2D, 0x46, 0xF2, 0x76, 0xC5, 0x7E, 0xE2, 0xA4, 0xE6, 0xD9, 0x6E, 0x48, 0x34, 0x2B,
|
||||
0xC6, 0x5F, 0xBC, 0xA0, 0x6D, 0x0D, 0x47, 0x6B, 0x95, 0x96, 0x92, 0x91, 0xB2, 0x27, 0xEB, 0x9E,
|
||||
0xEC, 0x8F, 0xDF, 0x9C, 0x74, 0x99, 0x64, 0xF5, 0xFF, 0x28, 0xB6, 0x37, 0xF3, 0x7C, 0x81, 0x03,
|
||||
0x44, 0x62, 0x1F, 0xDB, 0x04, 0x7B, 0xB0, 0x9B, 0x31, 0xA7, 0xDE, 0x78, 0x9F, 0xAD, 0x0E, 0x3F,
|
||||
0x3E, 0x4D, 0xC7, 0xD7, 0x39, 0x19, 0x5E, 0xC2, 0xD0, 0xAC, 0xE8, 0x1A, 0x87, 0x8B, 0x07, 0x05,
|
||||
0x22, 0xED, 0x72, 0x2E, 0x1D, 0xC1, 0xA9, 0xD6, 0xE0, 0x83, 0xD5, 0xD8, 0xCB, 0x80, 0xF0, 0x66,
|
||||
0x7A, 0x9D, 0x50, 0xF9, 0x10, 0x4E, 0x16, 0x14, 0x77, 0x75, 0x6A, 0x67, 0xD2, 0xC0, 0xA6, 0xC4,
|
||||
0x53, 0x8C, 0x32, 0xCA, 0x82, 0x2A, 0x18, 0x9A, 0xF4, 0x4C, 0x3D, 0x26, 0x12, 0xE7, 0x98, 0x2F,
|
||||
0x4A, 0x04, 0x0D, 0xAF, 0xB4, 0xCF, 0x12, 0xCE, 0x1A, 0x37, 0x61, 0x39, 0x60, 0x95, 0xBE, 0x25,
|
||||
0xE4, 0x6E, 0xFC, 0x1B, 0xE7, 0x49, 0xE6, 0x67, 0xF6, 0xC5, 0xCB, 0x2F, 0x27, 0xD4, 0x68, 0xB2,
|
||||
0x01, 0x52, 0xD0, 0x46, 0x11, 0x20, 0xFB, 0x9D, 0xA9, 0x02, 0xF5, 0x8F, 0x3D, 0x82, 0xD3, 0xFF,
|
||||
0x0B, 0xB8, 0xF2, 0x4D, 0x8E, 0x81, 0x2C, 0xAB, 0x5F, 0xC4, 0x41, 0x29, 0x40, 0xFA, 0xC0, 0xBF,
|
||||
0x33, 0x10, 0x21, 0x16, 0xB0, 0x71, 0x83, 0x96, 0x8D, 0x2B, 0x23, 0x3B, 0xF9, 0xC1, 0xE5, 0x72,
|
||||
0xE2, 0x1C, 0x26, 0xF0, 0x73, 0x36, 0x63, 0x56, 0x31, 0x4E, 0x6B, 0x55, 0x62, 0x79, 0xC6, 0x91,
|
||||
0x00, 0x35, 0xB1, 0x2A, 0xA6, 0x42, 0xDF, 0xEB, 0x3C, 0x51, 0xEA, 0x97, 0x57, 0x94, 0x8C, 0x80,
|
||||
0x34, 0x5C, 0xD2, 0x76, 0xA4, 0xE9, 0x85, 0xE8, 0xBB, 0x78, 0xE0, 0xB5, 0xAD, 0x0F, 0x87, 0x70,
|
||||
0xDD, 0xAE, 0xF4, 0xD9, 0x66, 0x54, 0x6F, 0xCC, 0x4C, 0x77, 0x3E, 0xCD, 0xF1, 0x75, 0x0A, 0xA1,
|
||||
0x28, 0x9B, 0x9A, 0x7E, 0x4B, 0x98, 0x99, 0x47, 0xFE, 0xA5, 0xF7, 0xB7, 0xA3, 0xE1, 0x9F, 0xBC,
|
||||
0x93, 0x44, 0x3A, 0x08, 0x89, 0x22, 0xEE, 0xB9, 0x45, 0xD6, 0x06, 0x09, 0xC9, 0xBD, 0x14, 0x0C,
|
||||
0xB6, 0x5E, 0x9C, 0x7A, 0x65, 0x59, 0xAA, 0x19, 0x5B, 0x7C, 0x18, 0x43, 0x92, 0x13, 0x15, 0x7B,
|
||||
0xED, 0xD5, 0xC7, 0x17, 0xEF, 0x86, 0x90, 0xC2, 0x74, 0x64, 0xF3, 0xDC, 0x6C, 0x38, 0x05, 0x1D,
|
||||
0xC8, 0x0E, 0xEC, 0x6A, 0x32, 0xDA, 0xD7, 0xC3, 0xDB, 0x8B, 0x24, 0xB3, 0x5D, 0x2E, 0xBA, 0xA2,
|
||||
0xD8, 0x03, 0x88, 0x7D, 0x7F, 0x69, 0x8A, 0xFD, 0xCA, 0x4F, 0x30, 0x9E, 0xA0, 0xD1, 0x5A, 0x53,
|
||||
0xDE, 0x3F, 0x84, 0xAC, 0xF8, 0xA7, 0x2D, 0x1F, 0x1E, 0xE3, 0x58, 0x50, 0x6D, 0x48, 0x07, 0xA8
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions - MPK file format
|
||||
|
||||
// This function converts MPK file header into MPQ file header
|
||||
DWORD ConvertMpkHeaderToFormat4(
|
||||
TMPQArchive * ha,
|
||||
ULONGLONG FileSize,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
TMPKHeader * pMpkHeader = (TMPKHeader *)ha->HeaderData;
|
||||
TMPQHeader Header;
|
||||
|
||||
// Can't open the archive with certain flags
|
||||
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
if(pMpkHeader->dwVersion != ID_MPK_VERSION_2000)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
// Translate the MPK header into a MPQ header
|
||||
// Note: Hash table size and block table size are in bytes, not in entries
|
||||
memset(&Header, 0, sizeof(TMPQHeader));
|
||||
Header.dwID = BSWAP_INT32_UNSIGNED(pMpkHeader->dwID);
|
||||
Header.dwArchiveSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwArchiveSize);
|
||||
Header.dwHeaderSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHeaderSize);
|
||||
Header.dwHashTablePos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHashTablePos);
|
||||
Header.dwHashTableSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwHashTableSize) / sizeof(TMPKHash);
|
||||
Header.dwBlockTablePos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwBlockTablePos);
|
||||
Header.dwBlockTableSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwBlockTableSize);
|
||||
// Header.dwUnknownPos = BSWAP_INT32_UNSIGNED(pMpkHeader->dwUnknownPos);
|
||||
// Header.dwUnknownSize = BSWAP_INT32_UNSIGNED(pMpkHeader->dwUnknownSize);
|
||||
assert(Header.dwHeaderSize == sizeof(TMPKHeader));
|
||||
|
||||
// Verify the MPK header
|
||||
if(Header.dwID == ID_MPK && Header.dwHeaderSize == sizeof(TMPKHeader) && Header.dwArchiveSize == (DWORD)FileSize)
|
||||
{
|
||||
// The header ID must be ID_MPQ
|
||||
Header.dwID = g_dwMpqSignature;
|
||||
Header.wFormatVersion = MPQ_FORMAT_VERSION_1;
|
||||
Header.wSectorSize = 3;
|
||||
|
||||
// Initialize the fields of 3.0 header
|
||||
Header.ArchiveSize64 = Header.dwArchiveSize;
|
||||
Header.HashTableSize64 = Header.dwHashTableSize * sizeof(TMPQHash);
|
||||
Header.BlockTableSize64 = Header.dwBlockTableSize * sizeof(TMPQBlock);
|
||||
|
||||
// Copy the converted MPQ header back
|
||||
memcpy(ha->HeaderData, &Header, sizeof(TMPQHeader));
|
||||
|
||||
// Mark this file as MPK file
|
||||
ha->pfnHashString = HashStringLower;
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
ha->dwSubType = MPQ_SUBTYPE_MPK;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
return ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Attempts to search a free hash entry in the hash table being converted.
|
||||
// The created hash table must always be of nonzero size,
|
||||
// should have no duplicated items and no deleted entries
|
||||
TMPQHash * FindFreeHashEntry(TMPQHash * pHashTable, DWORD dwHashTableSize, DWORD dwStartIndex)
|
||||
{
|
||||
TMPQHash * pHash;
|
||||
DWORD dwIndex;
|
||||
|
||||
// Set the initial index
|
||||
dwStartIndex = dwIndex = (dwStartIndex & (dwHashTableSize - 1));
|
||||
assert(dwHashTableSize != 0);
|
||||
|
||||
// Search the hash table and return the found entries in the following priority:
|
||||
for(;;)
|
||||
{
|
||||
// We are not expecting to find matching entry in the hash table being built
|
||||
// We are not expecting to find deleted entry either
|
||||
pHash = pHashTable + dwIndex;
|
||||
|
||||
// If we found a free entry, we need to stop searching
|
||||
if(pHash->dwBlockIndex == HASH_ENTRY_FREE)
|
||||
return pHash;
|
||||
|
||||
// Move to the next hash entry.
|
||||
// If we reached the starting entry, it's failure.
|
||||
dwIndex = (dwIndex + 1) & (dwHashTableSize - 1);
|
||||
if(dwIndex == dwStartIndex)
|
||||
break;
|
||||
}
|
||||
|
||||
// We haven't found anything
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD GetMpkBlockTableItemLength(void * pvMpkBlockTable, size_t cbMpkBlockTable)
|
||||
{
|
||||
TMPKBlock1 * pBlockItem1 = (TMPKBlock1 *)(pvMpkBlockTable);
|
||||
TMPKBlock2 * pBlockItem2 = (TMPKBlock2 *)(pvMpkBlockTable);
|
||||
|
||||
//
|
||||
// We have no information as to what's the type of the table item
|
||||
// So we just compare the magic numbers of all supported item sizes
|
||||
//
|
||||
|
||||
if(cbMpkBlockTable >= sizeof(TMPKBlock1) * 2)
|
||||
{
|
||||
if(pBlockItem1[0].dwMagic == pBlockItem1[1].dwMagic)
|
||||
{
|
||||
return sizeof(TMPKBlock1);
|
||||
}
|
||||
}
|
||||
|
||||
if(cbMpkBlockTable >= sizeof(TMPKBlock2) * 2)
|
||||
{
|
||||
if(pBlockItem2[0].dwMagic == pBlockItem2[1].dwMagic)
|
||||
{
|
||||
return sizeof(TMPKBlock2);
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown item size
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DecryptMpkTable(void * pvMpkTable, size_t cbSize)
|
||||
{
|
||||
LPBYTE pbMpkTable = (LPBYTE)pvMpkTable;
|
||||
|
||||
for(size_t i = 0; i < cbSize; i++)
|
||||
pbMpkTable[i] = MpkDecryptionKey[pbMpkTable[i]];
|
||||
}
|
||||
|
||||
void * LoadMpkTable(TMPQArchive * ha, DWORD dwByteOffset, DWORD cbTableSize)
|
||||
{
|
||||
ULONGLONG ByteOffset;
|
||||
LPBYTE pbMpkTable = NULL;
|
||||
|
||||
// Allocate space for the table
|
||||
pbMpkTable = STORM_ALLOC(BYTE, cbTableSize);
|
||||
if(pbMpkTable != NULL)
|
||||
{
|
||||
// Load and the MPK hash table
|
||||
ByteOffset = ha->MpqPos + dwByteOffset;
|
||||
if(FileStream_Read(ha->pStream, &ByteOffset, pbMpkTable, cbTableSize))
|
||||
{
|
||||
// Decrypt the table
|
||||
DecryptMpkTable(pbMpkTable, cbTableSize);
|
||||
return pbMpkTable;
|
||||
}
|
||||
|
||||
// Free the MPK table
|
||||
STORM_FREE(pbMpkTable);
|
||||
pbMpkTable = NULL;
|
||||
}
|
||||
|
||||
// Return the table
|
||||
return pbMpkTable;
|
||||
}
|
||||
|
||||
TMPQHash * LoadMpkHashTable(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TMPQHash * pHashTable = NULL;
|
||||
TMPKHash * pMpkHash;
|
||||
TMPQHash * pHash = NULL;
|
||||
DWORD dwHashTableSize = pHeader->dwHashTableSize;
|
||||
|
||||
// MPKs use different hash table searching.
|
||||
// Instead of using MPQ_HASH_TABLE_INDEX hash as index,
|
||||
// they store the value directly in the hash table.
|
||||
// Also for faster searching, the hash table is sorted ascending by the value
|
||||
|
||||
// Load and decrypt the MPK hash table.
|
||||
pMpkHash = (TMPKHash *)LoadMpkTable(ha, pHeader->dwHashTablePos, pHeader->dwHashTableSize * sizeof(TMPKHash));
|
||||
if(pMpkHash != NULL)
|
||||
{
|
||||
// Calculate the hash table size as if it was real MPQ hash table
|
||||
pHeader->dwHashTableSize = GetNearestPowerOfTwo(pHeader->dwHashTableSize);
|
||||
pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash);
|
||||
|
||||
// Now allocate table that will serve like a true MPQ hash table,
|
||||
// so we translate the MPK hash table to MPQ hash table
|
||||
pHashTable = STORM_ALLOC(TMPQHash, pHeader->dwHashTableSize);
|
||||
if(pHashTable != NULL)
|
||||
{
|
||||
// Set the entire hash table to free
|
||||
memset(pHashTable, 0xFF, (size_t)pHeader->HashTableSize64);
|
||||
|
||||
// Copy the MPK hash table into MPQ hash table
|
||||
for(DWORD i = 0; i < dwHashTableSize; i++)
|
||||
{
|
||||
// Finds the free hash entry in the hash table
|
||||
// We don't expect any errors here, because we are putting files to empty hash table
|
||||
pHash = FindFreeHashEntry(pHashTable, pHeader->dwHashTableSize, pMpkHash[i].dwName1);
|
||||
assert(pHash->dwBlockIndex == HASH_ENTRY_FREE);
|
||||
|
||||
// Copy the MPK hash entry to the hash table
|
||||
pHash->dwBlockIndex = pMpkHash[i].dwBlockIndex;
|
||||
pHash->Locale = 0;
|
||||
pHash->Platform = 0;
|
||||
pHash->Reserved = 0;
|
||||
pHash->dwName1 = pMpkHash[i].dwName2;
|
||||
pHash->dwName2 = pMpkHash[i].dwName3;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the temporary hash table
|
||||
STORM_FREE(pMpkHash);
|
||||
}
|
||||
|
||||
return pHashTable;
|
||||
}
|
||||
|
||||
static DWORD ConvertMpkFlagsToMpqFlags(DWORD dwMpkFlags)
|
||||
{
|
||||
DWORD dwMpqFlags = MPQ_FILE_EXISTS;
|
||||
|
||||
// Check for flags that are always present
|
||||
assert((dwMpkFlags & MPK_FILE_UNKNOWN_0001) != 0);
|
||||
assert((dwMpkFlags & MPK_FILE_UNKNOWN_0010) != 0);
|
||||
assert((dwMpkFlags & MPK_FILE_EXISTS) != 0);
|
||||
|
||||
// Append the compressed flag
|
||||
dwMpqFlags |= (dwMpkFlags & MPK_FILE_COMPRESSED) ? MPQ_FILE_COMPRESS : 0;
|
||||
dwMpqFlags |= (dwMpkFlags & MPK_FILE_ENCRYPTED) ? MPQ_FILE_ENCRYPTED : 0;
|
||||
|
||||
// All files in the MPQ seem to be single unit files
|
||||
dwMpqFlags |= MPQ_FILE_SINGLE_UNIT;
|
||||
|
||||
return dwMpqFlags;
|
||||
}
|
||||
|
||||
static TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha, void * pMpkBlockTable, DWORD nItemSize)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TMPQBlock * pBlockTable;
|
||||
TMPQBlock * pMpqBlock;
|
||||
LPBYTE pbMpkBlockPtr = (LPBYTE)(pMpkBlockTable);
|
||||
LPBYTE pbMpkBlockEnd = pbMpkBlockPtr + pHeader->dwBlockTableSize;
|
||||
|
||||
// Fixup the number of items in the MPK block table
|
||||
pHeader->dwBlockTableSize = pHeader->dwBlockTableSize / nItemSize;
|
||||
|
||||
// Allocate buffer for MPQ-like block table
|
||||
pBlockTable = pMpqBlock = STORM_ALLOC(TMPQBlock, pHeader->dwBlockTableSize);
|
||||
if(pBlockTable != NULL)
|
||||
{
|
||||
while(pbMpkBlockPtr < pbMpkBlockEnd)
|
||||
{
|
||||
TMPKBlock1 * pMpkBlock = (TMPKBlock1 *)(pbMpkBlockPtr);
|
||||
|
||||
// Translate the MPK block table entry to MPQ block table entry
|
||||
pMpqBlock->dwFilePos = pMpkBlock->dwFilePos;
|
||||
pMpqBlock->dwCSize = pMpkBlock->dwCSize;
|
||||
pMpqBlock->dwFSize = pMpkBlock->dwFSize;
|
||||
pMpqBlock->dwFlags = ConvertMpkFlagsToMpqFlags(pMpkBlock->dwFlags);
|
||||
|
||||
// Move both
|
||||
pbMpkBlockPtr += nItemSize;
|
||||
pMpqBlock++;
|
||||
}
|
||||
}
|
||||
|
||||
return pBlockTable;
|
||||
}
|
||||
|
||||
TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TMPQBlock * pBlockTable = NULL;
|
||||
void * pMpkBlockTable;
|
||||
DWORD nItemLength;
|
||||
|
||||
// Load the MPK block table. At this moment, we don't know the version of the blobk table
|
||||
pMpkBlockTable = LoadMpkTable(ha, pHeader->dwBlockTablePos, pHeader->dwBlockTableSize);
|
||||
if(pMpkBlockTable != NULL)
|
||||
{
|
||||
// Based on the item length, load the table and convert it to the MPQ table
|
||||
if((nItemLength = GetMpkBlockTableItemLength(pMpkBlockTable, pHeader->dwBlockTableSize)) != 0)
|
||||
{
|
||||
pBlockTable = LoadMpkBlockTable(ha, pMpkBlockTable, nItemLength);
|
||||
}
|
||||
|
||||
// Free the MPK block table
|
||||
STORM_FREE(pMpkBlockTable);
|
||||
}
|
||||
|
||||
return pBlockTable;
|
||||
}
|
||||
1183
vendor/stormlib-9/src/SCompression.cpp
vendored
Normal file
1183
vendor/stormlib-9/src/SCompression.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1337
vendor/stormlib-9/src/SFileAddFile.cpp
vendored
Normal file
1337
vendor/stormlib-9/src/SFileAddFile.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
573
vendor/stormlib-9/src/SFileAttributes.cpp
vendored
Normal file
573
vendor/stormlib-9/src/SFileAttributes.cpp
vendored
Normal file
@ -0,0 +1,573 @@
|
||||
/*****************************************************************************/
|
||||
/* SAttrFile.cpp Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SAttrFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures
|
||||
|
||||
typedef struct _MPQ_ATTRIBUTES_HEADER
|
||||
{
|
||||
DWORD dwVersion; // Version of the (attributes) file. Must be 100 (0x64)
|
||||
DWORD dwFlags; // See MPQ_ATTRIBUTE_XXXX
|
||||
|
||||
// Followed by an array of CRC32
|
||||
// Followed by an array of file times
|
||||
// Followed by an array of MD5
|
||||
// Followed by an array of patch bits
|
||||
|
||||
// Note: The MD5 in (attributes), if present, is a hash of the entire file.
|
||||
// In case the file is an incremental patch, it contains MD5 of the file
|
||||
// after being patched.
|
||||
|
||||
} MPQ_ATTRIBUTES_HEADER, *PMPQ_ATTRIBUTES_HEADER;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static DWORD GetSizeOfAttributesFile(DWORD dwAttrFlags, DWORD dwBlockTableSize)
|
||||
{
|
||||
DWORD cbAttrFile = sizeof(MPQ_ATTRIBUTES_HEADER);
|
||||
|
||||
// Calculate size of the (attributes) file
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
cbAttrFile += dwBlockTableSize * sizeof(DWORD);
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
|
||||
cbAttrFile += dwBlockTableSize * sizeof(ULONGLONG);
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_MD5)
|
||||
cbAttrFile += dwBlockTableSize * MD5_DIGEST_SIZE;
|
||||
|
||||
// The bit array has been created without the last bit belonging to (attributes)
|
||||
// When the number of files is a multiplier of 8 plus one, then the size of (attributes)
|
||||
// if 1 byte less than expected.
|
||||
// Example: wow-update-13164.MPQ: BlockTableSize = 0x62E1, but there's only 0xC5C bytes
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
|
||||
cbAttrFile += (dwBlockTableSize + 6) / 8;
|
||||
|
||||
return cbAttrFile;
|
||||
}
|
||||
|
||||
static DWORD CheckSizeOfAttributesFile(DWORD cbAttrFile, DWORD dwAttrFlags, DWORD dwBlockTableSize)
|
||||
{
|
||||
DWORD cbHeaderSize = sizeof(MPQ_ATTRIBUTES_HEADER);
|
||||
DWORD cbChecksumSize1 = 0;
|
||||
DWORD cbChecksumSize2 = 0;
|
||||
DWORD cbFileTimeSize1 = 0;
|
||||
DWORD cbFileTimeSize2 = 0;
|
||||
DWORD cbFileHashSize1 = 0;
|
||||
DWORD cbFileHashSize2 = 0;
|
||||
DWORD cbPatchBitSize1 = 0;
|
||||
DWORD cbPatchBitSize2 = 0;
|
||||
DWORD cbPatchBitSize3 = 0;
|
||||
|
||||
//
|
||||
// Various variants with the patch bit
|
||||
//
|
||||
// interface.MPQ.part from WoW build 10958 has
|
||||
// the MPQ_ATTRIBUTE_PATCH_BIT set, but there's an array of DWORDs instead.
|
||||
// The array is filled with zeros, so we don't know what it should contain
|
||||
//
|
||||
// Zenith.SC2MAP has the MPQ_ATTRIBUTE_PATCH_BIT set, but the bit array is missing
|
||||
//
|
||||
// Elimination Tournament 2.w3x's (attributes) have one entry less
|
||||
//
|
||||
// There may be two variants: Either the (attributes) file has full
|
||||
// number of entries, or has one entry less
|
||||
//
|
||||
|
||||
// Get the expected size of CRC32 array
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
{
|
||||
cbChecksumSize1 += dwBlockTableSize * sizeof(DWORD);
|
||||
cbChecksumSize2 += cbChecksumSize1 - sizeof(DWORD);
|
||||
}
|
||||
|
||||
// Get the expected size of FILETIME array
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
|
||||
{
|
||||
cbFileTimeSize1 += dwBlockTableSize * sizeof(ULONGLONG);
|
||||
cbFileTimeSize2 += cbFileTimeSize1 - sizeof(ULONGLONG);
|
||||
}
|
||||
|
||||
// Get the expected size of MD5 array
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_MD5)
|
||||
{
|
||||
cbFileHashSize1 += dwBlockTableSize * MD5_DIGEST_SIZE;
|
||||
cbFileHashSize2 += cbFileHashSize1 - MD5_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
// Get the expected size of patch bit array
|
||||
if(dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
|
||||
{
|
||||
cbPatchBitSize1 =
|
||||
cbPatchBitSize2 = ((dwBlockTableSize + 6) / 8);
|
||||
cbPatchBitSize3 = dwBlockTableSize * sizeof(DWORD);
|
||||
}
|
||||
|
||||
// Check if the (attributes) file entry count is equal to our file table size
|
||||
if(cbAttrFile == (cbHeaderSize + cbChecksumSize1 + cbFileTimeSize1 + cbFileHashSize1 + cbPatchBitSize1))
|
||||
return dwBlockTableSize;
|
||||
|
||||
// Check if the (attributes) file entry count is equal to our file table size minus one
|
||||
if(cbAttrFile == (cbHeaderSize + cbChecksumSize2 + cbFileTimeSize2 + cbFileHashSize2 + cbPatchBitSize2))
|
||||
return dwBlockTableSize - 1;
|
||||
|
||||
// Zenith.SC2MAP has the MPQ_ATTRIBUTE_PATCH_BIT set, but the bit array is missing
|
||||
if(cbAttrFile == (cbHeaderSize + cbChecksumSize1 + cbFileTimeSize1 + cbFileHashSize1))
|
||||
return dwBlockTableSize;
|
||||
|
||||
// interface.MPQ.part (WoW build 10958) has the MPQ_ATTRIBUTE_PATCH_BIT set
|
||||
// but there's an array of DWORDs (filled with zeros) instead of array of bits
|
||||
if(cbAttrFile == (cbHeaderSize + cbChecksumSize1 + cbFileTimeSize1 + cbFileHashSize1 + cbPatchBitSize3))
|
||||
return dwBlockTableSize;
|
||||
|
||||
#ifdef __STORMLIB_TEST__
|
||||
// Invalid size of the (attributes) file
|
||||
// Note that many MPQs, especially Warcraft III maps have the size of (attributes) invalid.
|
||||
// We only perform this check if this is the STORMLIB testprogram itself
|
||||
// assert(false);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD LoadAttributesFile(TMPQArchive * ha, LPBYTE pbAttrFile, DWORD cbAttrFile)
|
||||
{
|
||||
LPBYTE pbAttrFileEnd = pbAttrFile + cbAttrFile;
|
||||
LPBYTE pbAttrPtr = pbAttrFile;
|
||||
DWORD dwAttributesEntries = 0;
|
||||
DWORD i;
|
||||
|
||||
// Load and verify the header
|
||||
if((pbAttrPtr + sizeof(MPQ_ATTRIBUTES_HEADER)) <= pbAttrFileEnd)
|
||||
{
|
||||
PMPQ_ATTRIBUTES_HEADER pAttrHeader = (PMPQ_ATTRIBUTES_HEADER)pbAttrPtr;
|
||||
|
||||
// Verify the header version
|
||||
BSWAP_ARRAY32_UNSIGNED(pAttrHeader, sizeof(MPQ_ATTRIBUTES_HEADER));
|
||||
if(pAttrHeader->dwVersion != MPQ_ATTRIBUTES_V1)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Verify the flags
|
||||
if(pAttrHeader->dwFlags & ~MPQ_ATTRIBUTE_ALL)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Verify whether file size of (attributes) is expected
|
||||
dwAttributesEntries = CheckSizeOfAttributesFile(cbAttrFile, pAttrHeader->dwFlags, ha->pHeader->dwBlockTableSize);
|
||||
if(dwAttributesEntries == 0)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
ha->dwAttrFlags = pAttrHeader->dwFlags;
|
||||
pbAttrPtr = (LPBYTE)(pAttrHeader + 1);
|
||||
}
|
||||
|
||||
// Load the CRC32 (if present)
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
{
|
||||
LPDWORD ArrayCRC32 = (LPDWORD)pbAttrPtr;
|
||||
DWORD cbArraySize = dwAttributesEntries * sizeof(DWORD);
|
||||
|
||||
// Verify if there's enough data
|
||||
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
BSWAP_ARRAY32_UNSIGNED(ArrayCRC32, cbArraySize);
|
||||
for(i = 0; i < dwAttributesEntries; i++)
|
||||
ha->pFileTable[i].dwCrc32 = ArrayCRC32[i];
|
||||
pbAttrPtr += cbArraySize;
|
||||
}
|
||||
|
||||
// Load the FILETIME (if present)
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
|
||||
{
|
||||
ULONGLONG * ArrayFileTime = (ULONGLONG *)pbAttrPtr;
|
||||
DWORD cbArraySize = dwAttributesEntries * sizeof(ULONGLONG);
|
||||
|
||||
// Verify if there's enough data
|
||||
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
BSWAP_ARRAY64_UNSIGNED(ArrayFileTime, cbArraySize);
|
||||
for(i = 0; i < dwAttributesEntries; i++)
|
||||
ha->pFileTable[i].FileTime = ArrayFileTime[i];
|
||||
pbAttrPtr += cbArraySize;
|
||||
}
|
||||
|
||||
// Load the MD5 (if present)
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5)
|
||||
{
|
||||
LPBYTE ArrayMd5 = pbAttrPtr;
|
||||
DWORD cbArraySize = dwAttributesEntries * MD5_DIGEST_SIZE;
|
||||
|
||||
// Verify if there's enough data
|
||||
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
for(i = 0; i < dwAttributesEntries; i++)
|
||||
{
|
||||
memcpy(ha->pFileTable[i].md5, ArrayMd5, MD5_DIGEST_SIZE);
|
||||
ArrayMd5 += MD5_DIGEST_SIZE;
|
||||
}
|
||||
pbAttrPtr += cbArraySize;
|
||||
}
|
||||
|
||||
// Read the patch bit for each file (if present)
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
|
||||
{
|
||||
LPBYTE pbBitArray = pbAttrPtr;
|
||||
DWORD cbArraySize = (dwAttributesEntries + 7) / 8;
|
||||
DWORD dwByteIndex = 0;
|
||||
DWORD dwBitMask = 0x80;
|
||||
|
||||
// Verify if there's enough data
|
||||
if((pbAttrPtr + cbArraySize) == pbAttrFileEnd)
|
||||
{
|
||||
for(i = 0; i < dwAttributesEntries; i++)
|
||||
{
|
||||
ha->pFileTable[i].dwFlags |= (pbBitArray[dwByteIndex] & dwBitMask) ? MPQ_FILE_PATCH_FILE : 0;
|
||||
dwByteIndex += (dwBitMask & 0x01);
|
||||
dwBitMask = (dwBitMask << 0x07) | (dwBitMask >> 0x01);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
|
||||
{
|
||||
PMPQ_ATTRIBUTES_HEADER pAttrHeader;
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
LPBYTE pbAttrFile;
|
||||
LPBYTE pbAttrPtr;
|
||||
size_t cbAttrFile;
|
||||
|
||||
// Check if we need patch bits in the (attributes) file
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
{
|
||||
ha->dwAttrFlags |= MPQ_ATTRIBUTE_PATCH_BIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the buffer for holding the entire (attributes)
|
||||
// Allocate 1 byte more (See GetSizeOfAttributesFile for more info)
|
||||
cbAttrFile = GetSizeOfAttributesFile(ha->dwAttrFlags, ha->pHeader->dwBlockTableSize);
|
||||
pbAttrFile = pbAttrPtr = STORM_ALLOC(BYTE, cbAttrFile + 1);
|
||||
if(pbAttrFile != NULL)
|
||||
{
|
||||
// Make sure it's all zeroed
|
||||
memset(pbAttrFile, 0, cbAttrFile + 1);
|
||||
|
||||
// Write the header of the (attributes) file
|
||||
pAttrHeader = (PMPQ_ATTRIBUTES_HEADER)pbAttrPtr;
|
||||
pAttrHeader->dwVersion = BSWAP_INT32_UNSIGNED(100);
|
||||
pAttrHeader->dwFlags = BSWAP_INT32_UNSIGNED((ha->dwAttrFlags & MPQ_ATTRIBUTE_ALL));
|
||||
pbAttrPtr = (LPBYTE)(pAttrHeader + 1);
|
||||
|
||||
// Write the array of CRC32, if present
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
{
|
||||
LPDWORD pArrayCRC32 = (LPDWORD)pbAttrPtr;
|
||||
|
||||
// Copy from file table
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
*pArrayCRC32++ = BSWAP_INT32_UNSIGNED(pFileEntry->dwCrc32);
|
||||
|
||||
// Update pointer
|
||||
pbAttrPtr = (LPBYTE)pArrayCRC32;
|
||||
}
|
||||
|
||||
// Write the array of file time
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
|
||||
{
|
||||
ULONGLONG * pArrayFileTime = (ULONGLONG *)pbAttrPtr;
|
||||
|
||||
// Copy from file table
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
*pArrayFileTime++ = BSWAP_INT64_UNSIGNED(pFileEntry->FileTime);
|
||||
|
||||
// Update pointer
|
||||
pbAttrPtr = (LPBYTE)pArrayFileTime;
|
||||
}
|
||||
|
||||
// Write the array of MD5s
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5)
|
||||
{
|
||||
LPBYTE pbArrayMD5 = pbAttrPtr;
|
||||
|
||||
// Copy from file table
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
memcpy(pbArrayMD5, pFileEntry->md5, MD5_DIGEST_SIZE);
|
||||
pbArrayMD5 += MD5_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
// Update pointer
|
||||
pbAttrPtr = pbArrayMD5;
|
||||
}
|
||||
|
||||
// Write the array of patch bits
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
|
||||
{
|
||||
LPBYTE pbBitArray = pbAttrPtr;
|
||||
DWORD dwByteIndex = 0;
|
||||
BYTE dwBitMask = 0x80;
|
||||
|
||||
// Copy from file table
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Set the bit, if needed
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
pbBitArray[dwByteIndex] |= dwBitMask;
|
||||
|
||||
// Update bit index and bit mask
|
||||
dwByteIndex += (dwBitMask & 0x01);
|
||||
dwBitMask = (dwBitMask << 0x07) | (dwBitMask >> 0x01);
|
||||
}
|
||||
|
||||
// Move past the bit array
|
||||
pbAttrPtr += (ha->pHeader->dwBlockTableSize + 6) / 8;
|
||||
}
|
||||
|
||||
// Now we expect that current position matches the estimated size
|
||||
// Note that if there is 1 extra bit above the byte size,
|
||||
// the table is actually 1 byte shorter in Blizzard MPQs. See GetSizeOfAttributesFile
|
||||
assert((size_t)(pbAttrPtr - pbAttrFile) == cbAttrFile);
|
||||
}
|
||||
|
||||
// Give away the attributes file
|
||||
if(pcbAttrFile != NULL)
|
||||
*pcbAttrFile = (DWORD)cbAttrFile;
|
||||
return pbAttrFile;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions (internal use by StormLib)
|
||||
|
||||
DWORD SAttrLoadAttributes(TMPQArchive * ha)
|
||||
{
|
||||
HANDLE hFile = NULL;
|
||||
LPBYTE pbAttrFile;
|
||||
DWORD dwBytesRead;
|
||||
DWORD cbAttrFile = 0;
|
||||
DWORD dwErrCode = ERROR_FILE_CORRUPT;
|
||||
|
||||
// File table must be initialized
|
||||
assert(ha->pFileTable != NULL);
|
||||
assert((ha->dwFlags & MPQ_FLAG_BLOCK_TABLE_CUT) == 0);
|
||||
|
||||
// Don't load the attributes file from malformed Warcraft III maps
|
||||
if(ha->dwFlags & MPQ_FLAG_MALFORMED)
|
||||
return ERROR_FILE_CORRUPT;
|
||||
|
||||
// Attempt to open the "(attributes)" file.
|
||||
if(SFileOpenFileEx((HANDLE)ha, ATTRIBUTES_NAME, SFILE_OPEN_ANY_LOCALE, &hFile))
|
||||
{
|
||||
// Retrieve and check size of the (attributes) file
|
||||
cbAttrFile = SFileGetFileSize(hFile, NULL);
|
||||
|
||||
// Integer overflow check
|
||||
if((cbAttrFile + 1) > cbAttrFile)
|
||||
{
|
||||
// Size of the (attributes) might be 1 byte less than expected
|
||||
// See GetSizeOfAttributesFile for more info
|
||||
pbAttrFile = STORM_ALLOC(BYTE, cbAttrFile + 1);
|
||||
if(pbAttrFile != NULL)
|
||||
{
|
||||
// Set the last byte to 0 in case the size should be 1 byte greater
|
||||
pbAttrFile[cbAttrFile] = 0;
|
||||
|
||||
// Load the entire file to memory
|
||||
if(!SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL))
|
||||
ha->dwFlags |= (GetLastError() == ERROR_FILE_CORRUPT) ? MPQ_FLAG_MALFORMED : 0;
|
||||
|
||||
// Parse the (attributes)
|
||||
if(dwBytesRead == cbAttrFile)
|
||||
dwErrCode = LoadAttributesFile(ha, pbAttrFile, cbAttrFile);
|
||||
|
||||
// Free the buffer
|
||||
STORM_FREE(pbAttrFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the attributes file
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
// Saves the (attributes) to the MPQ
|
||||
DWORD SAttrFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
TMPQFile * hf = NULL;
|
||||
LPBYTE pbAttrFile;
|
||||
DWORD cbAttrFile = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Only save the attributes if we should do so
|
||||
if(ha->dwFileFlags2 != 0)
|
||||
{
|
||||
// At this point, we expect to have at least one reserved entry in the file table
|
||||
assert(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_NEW);
|
||||
assert(ha->dwReservedFiles > 0);
|
||||
|
||||
// Create the raw data that is to be written to (attributes)
|
||||
// Note: Blizzard MPQs have entries for (listfile) and (attributes),
|
||||
// but they are filled empty
|
||||
pbAttrFile = CreateAttributesFile(ha, &cbAttrFile);
|
||||
if(pbAttrFile != NULL)
|
||||
{
|
||||
// Determine the real flags for (attributes)
|
||||
if(ha->dwFileFlags2 == MPQ_FILE_DEFAULT_INTERNAL)
|
||||
ha->dwFileFlags2 = GetDefaultSpecialFileFlags(cbAttrFile, ha->pHeader->wFormatVersion);
|
||||
|
||||
// Create the attributes file in the MPQ
|
||||
dwErrCode = SFileAddFile_Init(ha, ATTRIBUTES_NAME,
|
||||
0,
|
||||
cbAttrFile,
|
||||
LANG_NEUTRAL,
|
||||
ha->dwFileFlags2 | MPQ_FILE_REPLACEEXISTING,
|
||||
&hf);
|
||||
|
||||
// Write the attributes file raw data to it
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Write the content of the attributes file to the MPQ
|
||||
dwErrCode = SFileAddFile_Write(hf, pbAttrFile, cbAttrFile, MPQ_COMPRESSION_ZLIB);
|
||||
SFileAddFile_Finish(hf);
|
||||
}
|
||||
|
||||
// Clear the number of reserved files
|
||||
ha->dwFlags &= ~(MPQ_FLAG_ATTRIBUTES_NEW | MPQ_FLAG_ATTRIBUTES_NONE);
|
||||
ha->dwReservedFiles--;
|
||||
|
||||
// Free the attributes buffer
|
||||
STORM_FREE(pbAttrFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the (attributes) file would be empty, its OK
|
||||
dwErrCode = (cbAttrFile == 0) ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
DWORD WINAPI SFileGetAttributes(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return SFILE_INVALID_ATTRIBUTES;
|
||||
}
|
||||
|
||||
return ha->dwAttrFlags;
|
||||
}
|
||||
|
||||
bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not allowed when the archive is read-only
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the attributes
|
||||
InvalidateInternalFiles(ha);
|
||||
ha->dwAttrFlags = (dwFlags & MPQ_ATTRIBUTE_ALL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName)
|
||||
{
|
||||
hash_state md5_state;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQFile * hf;
|
||||
BYTE Buffer[0x1000];
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwTotalBytes = 0;
|
||||
DWORD dwBytesRead;
|
||||
DWORD dwCrc32;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not allowed when the archive is read-only
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to open the file
|
||||
if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_BASE_FILE, &hFile))
|
||||
return false;
|
||||
|
||||
// Get the file size
|
||||
hf = (TMPQFile *)hFile;
|
||||
dwTotalBytes = hf->pFileEntry->dwFileSize;
|
||||
|
||||
// Initialize the CRC32 and MD5 contexts
|
||||
md5_init(&md5_state);
|
||||
dwCrc32 = crc32(0, Z_NULL, 0);
|
||||
|
||||
// Go through entire file and calculate both CRC32 and MD5
|
||||
while(dwTotalBytes != 0)
|
||||
{
|
||||
// Read data from file
|
||||
SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
|
||||
if(dwBytesRead == 0)
|
||||
break;
|
||||
|
||||
// Update CRC32 and MD5
|
||||
dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
|
||||
md5_process(&md5_state, Buffer, dwBytesRead);
|
||||
|
||||
// Decrement the total size
|
||||
dwTotalBytes -= dwBytesRead;
|
||||
}
|
||||
|
||||
// Update both CRC32 and MD5
|
||||
hf->pFileEntry->dwCrc32 = dwCrc32;
|
||||
md5_done(&md5_state, hf->pFileEntry->md5);
|
||||
|
||||
// Remember that we need to save the MPQ tables
|
||||
InvalidateInternalFiles(ha);
|
||||
SFileCloseFile(hFile);
|
||||
return true;
|
||||
}
|
||||
654
vendor/stormlib-9/src/SFileCompactArchive.cpp
vendored
Normal file
654
vendor/stormlib-9/src/SFileCompactArchive.cpp
vendored
Normal file
@ -0,0 +1,654 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Archive compacting function */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/* 21.04.13 1.02 Dea Compact callback now part of TMPQArchive */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static DWORD CheckIfAllFilesKnown(TMPQArchive * ha)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
DWORD dwBlockIndex = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Verify the file table
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++, dwBlockIndex++)
|
||||
{
|
||||
// If there is an existing entry in the file table, check its name
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
// The name must be valid and must not be a pseudo-name
|
||||
if(pFileEntry->szFileName == NULL || IsPseudoFileName(pFileEntry->szFileName, NULL))
|
||||
{
|
||||
dwErrCode = ERROR_UNKNOWN_FILE_NAMES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD CheckIfAllKeysKnown(TMPQArchive * ha, const TCHAR * szListFile, LPDWORD pFileKeys)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
DWORD dwBlockIndex = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Add the listfile to the MPQ
|
||||
if(szListFile != NULL)
|
||||
{
|
||||
// Notify the user
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_CHECKING_FILES, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
|
||||
dwErrCode = SFileAddListFile((HANDLE)ha, szListFile);
|
||||
}
|
||||
|
||||
// Verify the file table
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++, dwBlockIndex++)
|
||||
{
|
||||
// If the file exists and it's encrypted
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
// If we know the name, we decrypt the file key from the file name
|
||||
if(pFileEntry->szFileName != NULL && !IsPseudoFileName(pFileEntry->szFileName, NULL))
|
||||
{
|
||||
// Give the key to the caller
|
||||
pFileKeys[dwBlockIndex] = DecryptFileKey(pFileEntry->szFileName,
|
||||
pFileEntry->ByteOffset,
|
||||
pFileEntry->dwFileSize,
|
||||
pFileEntry->dwFlags);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't know the encryption key of this file,
|
||||
// thus we cannot compact the file
|
||||
dwErrCode = ERROR_UNKNOWN_FILE_NAMES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD CopyNonMpqData(
|
||||
TMPQArchive * ha,
|
||||
TFileStream * pSrcStream,
|
||||
TFileStream * pTrgStream,
|
||||
ULONGLONG & ByteOffset,
|
||||
ULONGLONG & ByteCount)
|
||||
{
|
||||
ULONGLONG DataSize = ByteCount;
|
||||
DWORD dwToRead;
|
||||
char DataBuffer[0x1000];
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Copy the data
|
||||
while(DataSize > 0)
|
||||
{
|
||||
// Get the proper size of data
|
||||
dwToRead = sizeof(DataBuffer);
|
||||
if(DataSize < dwToRead)
|
||||
dwToRead = (DWORD)DataSize;
|
||||
|
||||
// Read from the source stream
|
||||
if(!FileStream_Read(pSrcStream, &ByteOffset, DataBuffer, dwToRead))
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Write to the target stream
|
||||
if(!FileStream_Write(pTrgStream, NULL, DataBuffer, dwToRead))
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the progress
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
{
|
||||
ha->CompactBytesProcessed += dwToRead;
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_COPYING_NON_MPQ_DATA, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Decrement the number of data to be copied
|
||||
ByteOffset += dwToRead;
|
||||
DataSize -= dwToRead;
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
// Copies all file sectors into another archive.
|
||||
static DWORD CopyMpqFileSectors(
|
||||
TMPQArchive * ha,
|
||||
TMPQFile * hf,
|
||||
TFileStream * pNewStream,
|
||||
ULONGLONG MpqFilePos) // MPQ file position in the new archive
|
||||
{
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
ULONGLONG RawFilePos; // Used for calculating sector offset in the old MPQ archive
|
||||
DWORD dwBytesToCopy = pFileEntry->dwCmpSize;
|
||||
DWORD dwPatchSize = 0; // Size of patch header
|
||||
DWORD dwFileKey1 = 0; // File key used for decryption
|
||||
DWORD dwFileKey2 = 0; // File key used for encryption
|
||||
DWORD dwCmpSize = 0; // Compressed file size, including patch header
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Resolve decryption keys. Note that the file key given
|
||||
// in the TMPQFile structure also includes the key adjustment
|
||||
if(dwErrCode == ERROR_SUCCESS && (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED))
|
||||
{
|
||||
dwFileKey2 = dwFileKey1 = hf->dwFileKey;
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_KEY_V2)
|
||||
{
|
||||
dwFileKey2 = (dwFileKey1 ^ pFileEntry->dwFileSize) - (DWORD)pFileEntry->ByteOffset;
|
||||
dwFileKey2 = (dwFileKey2 + (DWORD)MpqFilePos) ^ pFileEntry->dwFileSize;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have to save patch header, do it
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->pPatchInfo != NULL)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pPatchInfo, sizeof(DWORD) * 3);
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->pPatchInfo, hf->pPatchInfo->dwLength))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
// Save the size of the patch info
|
||||
dwPatchSize = hf->pPatchInfo->dwLength;
|
||||
}
|
||||
|
||||
// If we have to save sector offset table, do it.
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->SectorOffsets != NULL)
|
||||
{
|
||||
DWORD * SectorOffsetsCopy = STORM_ALLOC(DWORD, hf->SectorOffsets[0] / sizeof(DWORD));
|
||||
DWORD dwSectorOffsLen = hf->SectorOffsets[0];
|
||||
|
||||
assert((pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) == 0);
|
||||
assert(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK);
|
||||
|
||||
if(SectorOffsetsCopy == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Encrypt the secondary sector offset table and write it to the target file
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorOffsLen);
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
EncryptMpqBlock(SectorOffsetsCopy, dwSectorOffsLen, dwFileKey2 - 1);
|
||||
|
||||
BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen);
|
||||
if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorOffsLen))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
dwBytesToCopy -= dwSectorOffsLen;
|
||||
dwCmpSize += dwSectorOffsLen;
|
||||
}
|
||||
|
||||
// Update compact progress
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
{
|
||||
ha->CompactBytesProcessed += dwSectorOffsLen;
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_COMPACTING_FILES, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
}
|
||||
|
||||
STORM_FREE(SectorOffsetsCopy);
|
||||
}
|
||||
|
||||
// Now we have to copy all file sectors. We do it without
|
||||
// recompression, because recompression is not necessary in this case
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
for(DWORD dwSector = 0; dwSector < hf->dwSectorCount; dwSector++)
|
||||
{
|
||||
DWORD dwRawDataInSector = hf->dwSectorSize;
|
||||
DWORD dwRawByteOffset = dwSector * hf->dwSectorSize;
|
||||
|
||||
// Fix the raw data length if the file is compressed
|
||||
if(hf->SectorOffsets != NULL)
|
||||
{
|
||||
dwRawDataInSector = hf->SectorOffsets[dwSector+1] - hf->SectorOffsets[dwSector];
|
||||
dwRawByteOffset = hf->SectorOffsets[dwSector];
|
||||
}
|
||||
|
||||
// Last sector: If there is not enough bytes remaining in the file, cut the raw size
|
||||
if(dwRawDataInSector > dwBytesToCopy)
|
||||
dwRawDataInSector = dwBytesToCopy;
|
||||
|
||||
// Calculate the raw file offset of the file sector
|
||||
RawFilePos = CalculateRawSectorOffset(hf, dwRawByteOffset);
|
||||
|
||||
// Read the file sector
|
||||
if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// If necessary, re-encrypt the sector
|
||||
// Note: Recompression is not necessary here. Unlike encryption,
|
||||
// the compression does not depend on the position of the file in MPQ.
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey1 != dwFileKey2)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
|
||||
DecryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey1 + dwSector);
|
||||
EncryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey2 + dwSector);
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
|
||||
}
|
||||
|
||||
// Now write the sector back to the file
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->pbFileSector, dwRawDataInSector))
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update compact progress
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
{
|
||||
ha->CompactBytesProcessed += dwRawDataInSector;
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_COMPACTING_FILES, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Adjust byte counts
|
||||
dwBytesToCopy -= dwRawDataInSector;
|
||||
dwCmpSize += dwRawDataInSector;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the sector CRCs, if any
|
||||
// Sector CRCs are always compressed (not imploded) and unencrypted
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->SectorOffsets != NULL && hf->SectorChksums != NULL)
|
||||
{
|
||||
DWORD dwCrcLength;
|
||||
|
||||
dwCrcLength = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount];
|
||||
if(dwCrcLength != 0)
|
||||
{
|
||||
if(!FileStream_Read(ha->pStream, NULL, hf->SectorChksums, dwCrcLength))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->SectorChksums, dwCrcLength))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
// Update compact progress
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
{
|
||||
ha->CompactBytesProcessed += dwCrcLength;
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_COMPACTING_FILES, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Size of the CRC block is also included in the compressed file size
|
||||
dwBytesToCopy -= dwCrcLength;
|
||||
dwCmpSize += dwCrcLength;
|
||||
}
|
||||
}
|
||||
|
||||
// There might be extra data beyond sector checksum table
|
||||
// Sometimes, these data are even part of sector offset table
|
||||
// Examples:
|
||||
// 2012 - WoW\15354\locale-enGB.MPQ:DBFilesClient\SpellLevels.dbc
|
||||
// 2012 - WoW\15354\locale-enGB.MPQ:Interface\AddOns\Blizzard_AuctionUI\Blizzard_AuctionUI.xml
|
||||
if(dwErrCode == ERROR_SUCCESS && dwBytesToCopy != 0)
|
||||
{
|
||||
LPBYTE pbExtraData;
|
||||
|
||||
// Allocate space for the extra data
|
||||
pbExtraData = STORM_ALLOC(BYTE, dwBytesToCopy);
|
||||
if(pbExtraData != NULL)
|
||||
{
|
||||
if(!FileStream_Read(ha->pStream, NULL, pbExtraData, dwBytesToCopy))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
if(!FileStream_Write(pNewStream, NULL, pbExtraData, dwBytesToCopy))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
// Include these extra data in the compressed size
|
||||
dwCmpSize += dwBytesToCopy;
|
||||
STORM_FREE(pbExtraData);
|
||||
}
|
||||
else
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Write the MD5's of the raw file data, if needed
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
|
||||
{
|
||||
dwErrCode = WriteMpqDataMD5(pNewStream,
|
||||
ha->MpqPos + MpqFilePos,
|
||||
pFileEntry->dwCmpSize,
|
||||
ha->pHeader->dwRawChunkSize);
|
||||
}
|
||||
|
||||
// Verify the number of bytes written
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// At this point, number of bytes written should be exactly
|
||||
// the same like the compressed file size. If it isn't,
|
||||
// there's something wrong (an unknown archive version, MPQ malformation, ...)
|
||||
//
|
||||
// Note: Diablo savegames have very weird layout, and the file "hero"
|
||||
// seems to have improper compressed size. Instead of real compressed size,
|
||||
// the "dwCmpSize" member of the block table entry contains
|
||||
// uncompressed size of file data + size of the sector table.
|
||||
// If we compact the archive, Diablo will refuse to load the game
|
||||
//
|
||||
// Note: Some patch files in WOW patches don't count the patch header
|
||||
// into compressed size
|
||||
//
|
||||
|
||||
if(!(dwCmpSize <= pFileEntry->dwCmpSize && pFileEntry->dwCmpSize <= dwCmpSize + dwPatchSize))
|
||||
{
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf = NULL;
|
||||
ULONGLONG MpqFilePos;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Walk through all files and write them to the destination MPQ archive
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Copy all the file sectors
|
||||
// Only do that when the file has nonzero size
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_EXISTS))
|
||||
{
|
||||
// Query the position where the destination file will be
|
||||
FileStream_GetPos(pNewStream, &MpqFilePos);
|
||||
MpqFilePos = MpqFilePos - ha->MpqPos;
|
||||
|
||||
// Perform file copy ONLY if the file has nonzero size
|
||||
if(pFileEntry->dwFileSize != 0)
|
||||
{
|
||||
// Allocate structure for the MPQ file
|
||||
hf = CreateFileHandle(ha, pFileEntry);
|
||||
if(hf == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Set the file decryption key
|
||||
hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable];
|
||||
|
||||
// If the file is a patch file, load the patch header
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
{
|
||||
dwErrCode = AllocatePatchInfo(hf, true);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate buffers for file sector and sector offset table
|
||||
dwErrCode = AllocateSectorBuffer(hf);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Also allocate sector offset table and sector checksum table
|
||||
dwErrCode = AllocateSectorOffsets(hf, true);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Also load sector checksums, if any
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)
|
||||
{
|
||||
dwErrCode = AllocateSectorChecksums(hf, false);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy all file sectors
|
||||
dwErrCode = CopyMpqFileSectors(ha, hf, pNewStream, MpqFilePos);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Free buffers. This also sets "hf" to NULL.
|
||||
FreeFileHandle(hf);
|
||||
}
|
||||
|
||||
// Note: DO NOT update the compressed size in the file entry, no matter how bad it is.
|
||||
pFileEntry->ByteOffset = MpqFilePos;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
if(hf != NULL)
|
||||
FreeFileHandle(hf);
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Changing hash table size
|
||||
|
||||
DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
return ha->dwMaxFileCount;
|
||||
}
|
||||
|
||||
bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
DWORD dwNewHashTableSize = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
dwErrCode = ERROR_INVALID_HANDLE;
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
dwErrCode = ERROR_ACCESS_DENIED;
|
||||
if(dwMaxFileCount < ha->dwFileTableSize)
|
||||
dwErrCode = ERROR_DISK_FULL;
|
||||
|
||||
// ALL file names must be known in order to be able to rebuild hash table
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->pHashTable != NULL)
|
||||
{
|
||||
dwErrCode = CheckIfAllFilesKnown(ha);
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Calculate the hash table size for the new file limit
|
||||
dwNewHashTableSize = GetNearestPowerOfTwo(dwMaxFileCount);
|
||||
|
||||
// Rebuild both file tables
|
||||
dwErrCode = RebuildFileTable(ha, dwNewHashTableSize);
|
||||
}
|
||||
}
|
||||
|
||||
// We always have to rebuild the (attributes) file due to file table change
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Invalidate (listfile) and (attributes)
|
||||
InvalidateInternalFiles(ha);
|
||||
|
||||
// Rebuild the HET table, if we have any
|
||||
if(ha->pHetTable != NULL)
|
||||
dwErrCode = RebuildHetTable(ha);
|
||||
}
|
||||
|
||||
// Return the error
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Archive compacting
|
||||
|
||||
bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK pfnCompactCB, void * pvUserData)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *) hMpq;
|
||||
|
||||
if (!IsValidMpqHandle(hMpq))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
ha->pfnCompactCB = pfnCompactCB;
|
||||
ha->pvCompactUserData = pvUserData;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WINAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool /* bReserved */)
|
||||
{
|
||||
TFileStream * pTempStream = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
ULONGLONG ByteOffset;
|
||||
ULONGLONG ByteCount;
|
||||
LPDWORD pFileKeys = NULL;
|
||||
TCHAR szTempFile[MAX_PATH+1] = _T("");
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
dwErrCode = ERROR_INVALID_HANDLE;
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
dwErrCode = ERROR_ACCESS_DENIED;
|
||||
|
||||
// If the MPQ is changed at this moment, we have to flush the archive
|
||||
if(dwErrCode == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_CHANGED))
|
||||
{
|
||||
SFileFlushArchive(hMpq);
|
||||
}
|
||||
|
||||
// Create the table with file keys
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
if((pFileKeys = STORM_ALLOC(DWORD, ha->dwFileTableSize)) != NULL)
|
||||
memset(pFileKeys, 0, sizeof(DWORD) * ha->dwFileTableSize);
|
||||
else
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// First of all, we have to check of we are able to decrypt all files.
|
||||
// If not, sorry, but the archive cannot be compacted.
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Initialize the progress variables for compact callback
|
||||
FileStream_GetSize(ha->pStream, &(ha->CompactTotalBytes));
|
||||
ha->CompactBytesProcessed = 0;
|
||||
dwErrCode = CheckIfAllKeysKnown(ha, szListFile, pFileKeys);
|
||||
}
|
||||
|
||||
// Get the temporary file name and create it
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Create temporary file name. Prevent buffer overflow
|
||||
StringCopy(szTempFile, _countof(szTempFile), FileStream_GetFileName(ha->pStream));
|
||||
StringCat(szTempFile, _countof(szTempFile), _T(".tmp"));
|
||||
|
||||
// Create temporary file
|
||||
pTempStream = FileStream_CreateFile(szTempFile, STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
|
||||
if(pTempStream == NULL)
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
|
||||
// Write the data before MPQ user data (if any)
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->UserDataPos != 0)
|
||||
{
|
||||
// Inform the application about the progress
|
||||
if(ha->pfnCompactCB != NULL)
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_COPYING_NON_MPQ_DATA, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
|
||||
ByteOffset = 0;
|
||||
ByteCount = ha->UserDataPos;
|
||||
dwErrCode = CopyNonMpqData(ha, ha->pStream, pTempStream, ByteOffset, ByteCount);
|
||||
}
|
||||
|
||||
// Write the MPQ user data (if any)
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->MpqPos > ha->UserDataPos)
|
||||
{
|
||||
// At this point, we assume that the user data size is equal
|
||||
// to pUserData->dwHeaderOffs.
|
||||
// If this assumption doesn't work, then we have an unknown version of MPQ
|
||||
ByteOffset = ha->UserDataPos;
|
||||
ByteCount = ha->MpqPos - ha->UserDataPos;
|
||||
|
||||
assert(ha->pUserData != NULL);
|
||||
assert(ha->pUserData->dwHeaderOffs == ByteCount);
|
||||
dwErrCode = CopyNonMpqData(ha, ha->pStream, pTempStream, ByteOffset, ByteCount);
|
||||
}
|
||||
|
||||
// Write the MPQ header
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
TMPQHeader SaveMpqHeader;
|
||||
|
||||
// Write the MPQ header to the file
|
||||
memcpy(&SaveMpqHeader, ha->pHeader, ha->pHeader->dwHeaderSize);
|
||||
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_1);
|
||||
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_2);
|
||||
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_3);
|
||||
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_4);
|
||||
if(!FileStream_Write(pTempStream, NULL, &SaveMpqHeader, ha->pHeader->dwHeaderSize))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
// Update the progress
|
||||
ha->CompactBytesProcessed += ha->pHeader->dwHeaderSize;
|
||||
}
|
||||
|
||||
// Now copy all files
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
dwErrCode = CopyMpqFiles(ha, pFileKeys, pTempStream);
|
||||
|
||||
// If succeeded, switch the streams
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
if(FileStream_Replace(ha->pStream, pTempStream))
|
||||
pTempStream = NULL;
|
||||
else
|
||||
dwErrCode = ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// Final user notification
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->pfnCompactCB != NULL)
|
||||
{
|
||||
ha->CompactBytesProcessed += (ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
|
||||
ha->CompactBytesProcessed += (ha->dwFileTableSize * sizeof(TMPQBlock));
|
||||
ha->pfnCompactCB(ha->pvCompactUserData, CCB_CLOSING_ARCHIVE, ha->CompactBytesProcessed, ha->CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
if(pTempStream != NULL)
|
||||
FileStream_Close(pTempStream);
|
||||
if(pFileKeys != NULL)
|
||||
STORM_FREE(pFileKeys);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
285
vendor/stormlib-9/src/SFileCreateArchive.cpp
vendored
Normal file
285
vendor/stormlib-9/src/SFileCreateArchive.cpp
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCreateArchive.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MPQ Editing functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */
|
||||
/* 08.06.10 1.00 Lad Renamed to SFileCreateArchive.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
|
||||
static const DWORD MpqHeaderSizes[] =
|
||||
{
|
||||
MPQ_HEADER_SIZE_V1,
|
||||
MPQ_HEADER_SIZE_V2,
|
||||
MPQ_HEADER_SIZE_V3,
|
||||
MPQ_HEADER_SIZE_V4
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static DWORD GetValidFileFlags(DWORD dwMpqVersion)
|
||||
{
|
||||
if(dwMpqVersion > MPQ_FORMAT_VERSION_1)
|
||||
return MPQ_FILE_VALID_FLAGS;
|
||||
return MPQ_FILE_VALID_FLAGS_W3X;
|
||||
}
|
||||
|
||||
static USHORT GetSectorSizeShift(DWORD dwSectorSize)
|
||||
{
|
||||
USHORT wSectorSizeShift = 0;
|
||||
|
||||
while(dwSectorSize > 0x200)
|
||||
{
|
||||
dwSectorSize >>= 1;
|
||||
wSectorSizeShift++;
|
||||
}
|
||||
|
||||
return wSectorSizeShift;
|
||||
}
|
||||
|
||||
static DWORD WriteNakedMPQHeader(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TMPQHeader Header;
|
||||
DWORD dwBytesToWrite = pHeader->dwHeaderSize;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Prepare the naked MPQ header
|
||||
memset(&Header, 0, sizeof(TMPQHeader));
|
||||
Header.dwID = pHeader->dwID;
|
||||
Header.dwHeaderSize = pHeader->dwHeaderSize;
|
||||
Header.dwArchiveSize = pHeader->dwHeaderSize;
|
||||
Header.wFormatVersion = pHeader->wFormatVersion;
|
||||
Header.wSectorSize = pHeader->wSectorSize;
|
||||
|
||||
// Write it to the file
|
||||
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_1);
|
||||
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_2);
|
||||
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_3);
|
||||
BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_4);
|
||||
if(!FileStream_Write(ha->pStream, &ha->MpqPos, &Header, dwBytesToWrite))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a new MPQ archive.
|
||||
|
||||
bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwCreateFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
|
||||
{
|
||||
SFILE_CREATE_MPQ CreateInfo;
|
||||
|
||||
// Fill the create structure
|
||||
memset(&CreateInfo, 0, sizeof(SFILE_CREATE_MPQ));
|
||||
CreateInfo.cbSize = sizeof(SFILE_CREATE_MPQ);
|
||||
CreateInfo.dwMpqVersion = (dwCreateFlags & MPQ_CREATE_ARCHIVE_VMASK) >> FLAGS_TO_FORMAT_SHIFT;
|
||||
CreateInfo.dwStreamFlags = STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE;
|
||||
CreateInfo.dwFileFlags1 = (dwCreateFlags & MPQ_CREATE_LISTFILE) ? MPQ_FILE_DEFAULT_INTERNAL : 0;
|
||||
CreateInfo.dwFileFlags2 = (dwCreateFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_FILE_DEFAULT_INTERNAL : 0;
|
||||
CreateInfo.dwFileFlags3 = (dwCreateFlags & MPQ_CREATE_SIGNATURE) ? MPQ_FILE_DEFAULT_INTERNAL : 0;
|
||||
CreateInfo.dwAttrFlags = (dwCreateFlags & MPQ_CREATE_ATTRIBUTES) ? (MPQ_ATTRIBUTE_CRC32 | MPQ_ATTRIBUTE_FILETIME | MPQ_ATTRIBUTE_MD5) : 0;
|
||||
CreateInfo.dwSectorSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000;
|
||||
CreateInfo.dwRawChunkSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_4) ? 0x4000 : 0;
|
||||
CreateInfo.dwMaxFileCount = dwMaxFileCount;
|
||||
|
||||
// Set the proper attribute parts
|
||||
if((CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_3) && (dwCreateFlags & MPQ_CREATE_ATTRIBUTES))
|
||||
CreateInfo.dwAttrFlags |= MPQ_ATTRIBUTE_PATCH_BIT;
|
||||
|
||||
// Backward compatibility: SFileCreateArchive always used to add (listfile)
|
||||
// We would break loads of applications if we change that
|
||||
CreateInfo.dwFileFlags1 = MPQ_FILE_DEFAULT_INTERNAL;
|
||||
|
||||
// Let the main function create the archive
|
||||
return SFileCreateArchive2(szMpqName, &CreateInfo, phMpq);
|
||||
}
|
||||
|
||||
bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq)
|
||||
{
|
||||
TFileStream * pStream = NULL; // File stream
|
||||
TMPQArchive * ha = NULL; // MPQ archive handle
|
||||
TMPQHeader * pHeader;
|
||||
ULONGLONG MpqPos = 0; // Position of MPQ header in the file
|
||||
HANDLE hMpq = NULL;
|
||||
DWORD dwBlockTableSize = 0; // Initial block table size
|
||||
DWORD dwHashTableSize = 0;
|
||||
DWORD dwReservedFiles = 0; // Number of reserved file entries
|
||||
DWORD dwMpqFlags = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters, if they are valid
|
||||
if(szMpqName == NULL || *szMpqName == 0 || pCreateInfo == NULL || phMpq == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify if all variables in SFILE_CREATE_MPQ are correct
|
||||
if((pCreateInfo->cbSize == 0 || pCreateInfo->cbSize > sizeof(SFILE_CREATE_MPQ)) ||
|
||||
(pCreateInfo->dwMpqVersion > MPQ_FORMAT_VERSION_4) ||
|
||||
(pCreateInfo->pvUserData != NULL || pCreateInfo->cbUserData != 0) ||
|
||||
(pCreateInfo->dwAttrFlags & ~MPQ_ATTRIBUTE_ALL) ||
|
||||
(pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1)) ||
|
||||
(pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1)))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// One time initialization of MPQ cryptography
|
||||
InitializeMpqCryptography();
|
||||
|
||||
// We verify if the file already exists and if it's a MPQ archive.
|
||||
// If yes, we won't allow to overwrite it.
|
||||
if(SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE | MPQ_OPEN_NO_ATTRIBUTES | MPQ_OPEN_NO_LISTFILE, &hMpq))
|
||||
{
|
||||
SFileCloseArchive(hMpq);
|
||||
SetLastError(ERROR_ALREADY_EXISTS);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// At this point, we have to create the archive.
|
||||
// - If the file exists, convert it to MPQ archive.
|
||||
// - If the file doesn't exist, create new empty file
|
||||
//
|
||||
|
||||
pStream = FileStream_OpenFile(szMpqName, pCreateInfo->dwStreamFlags);
|
||||
if(pStream == NULL)
|
||||
{
|
||||
pStream = FileStream_CreateFile(szMpqName, pCreateInfo->dwStreamFlags);
|
||||
if(pStream == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Increment the maximum amount of files to have space for (listfile)
|
||||
if(pCreateInfo->dwMaxFileCount && pCreateInfo->dwFileFlags1)
|
||||
{
|
||||
dwMpqFlags |= MPQ_FLAG_LISTFILE_NEW;
|
||||
dwReservedFiles++;
|
||||
}
|
||||
|
||||
// Increment the maximum amount of files to have space for (attributes)
|
||||
if(pCreateInfo->dwMaxFileCount && pCreateInfo->dwFileFlags2 && pCreateInfo->dwAttrFlags)
|
||||
{
|
||||
dwMpqFlags |= MPQ_FLAG_ATTRIBUTES_NEW;
|
||||
dwReservedFiles++;
|
||||
}
|
||||
|
||||
// Increment the maximum amount of files to have space for (signature)
|
||||
if(pCreateInfo->dwMaxFileCount && pCreateInfo->dwFileFlags3)
|
||||
{
|
||||
dwMpqFlags |= MPQ_FLAG_SIGNATURE_NEW;
|
||||
dwReservedFiles++;
|
||||
}
|
||||
|
||||
// If file count is not zero, initialize the hash table size
|
||||
dwHashTableSize = GetNearestPowerOfTwo(pCreateInfo->dwMaxFileCount + dwReservedFiles);
|
||||
|
||||
// Retrieve the file size and round it up to 0x200 bytes
|
||||
FileStream_GetSize(pStream, &MpqPos);
|
||||
MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL;
|
||||
if(!FileStream_SetSize(pStream, MpqPos))
|
||||
dwErrCode = GetLastError();
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Debug code, used for testing StormLib
|
||||
// dwBlockTableSize = dwHashTableSize * 2;
|
||||
#endif
|
||||
|
||||
// Create the archive handle
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Fill the MPQ archive handle structure
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
ha->pfnHashString = HashStringSlash;
|
||||
ha->pStream = pStream;
|
||||
ha->dwSectorSize = pCreateInfo->dwSectorSize;
|
||||
ha->UserDataPos = MpqPos;
|
||||
ha->MpqPos = MpqPos;
|
||||
ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData;
|
||||
ha->dwMaxFileCount = dwHashTableSize;
|
||||
ha->dwFileTableSize = 0;
|
||||
ha->dwReservedFiles = dwReservedFiles;
|
||||
ha->dwValidFileFlags = GetValidFileFlags(pCreateInfo->dwMpqVersion);
|
||||
ha->dwFileFlags1 = pCreateInfo->dwFileFlags1;
|
||||
ha->dwFileFlags2 = pCreateInfo->dwFileFlags2;
|
||||
ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0;
|
||||
ha->dwAttrFlags = pCreateInfo->dwAttrFlags;
|
||||
ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED;
|
||||
pStream = NULL;
|
||||
|
||||
// Fill the MPQ header
|
||||
memset(pHeader, 0, sizeof(ha->HeaderData));
|
||||
pHeader->dwID = g_dwMpqSignature;
|
||||
pHeader->dwHeaderSize = MpqHeaderSizes[pCreateInfo->dwMpqVersion];
|
||||
pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
|
||||
pHeader->wFormatVersion = (USHORT)pCreateInfo->dwMpqVersion;
|
||||
pHeader->wSectorSize = GetSectorSizeShift(ha->dwSectorSize);
|
||||
pHeader->dwHashTablePos = pHeader->dwHeaderSize;
|
||||
pHeader->dwHashTableSize = dwHashTableSize;
|
||||
pHeader->dwBlockTablePos = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash);
|
||||
pHeader->dwBlockTableSize = dwBlockTableSize;
|
||||
|
||||
// Set the mask for MPQ byte offset
|
||||
ha->FileOffsetMask = GetFileOffsetMask(ha);
|
||||
|
||||
// For MPQs version 4 and higher, we set the size of raw data block
|
||||
// for calculating MD5
|
||||
if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4)
|
||||
pHeader->dwRawChunkSize = pCreateInfo->dwRawChunkSize;
|
||||
|
||||
// Write the naked MPQ header
|
||||
dwErrCode = WriteNakedMPQHeader(ha);
|
||||
}
|
||||
|
||||
// Create initial HET table, if the caller required an MPQ format 3.0 or newer
|
||||
if(dwErrCode == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3 && pCreateInfo->dwMaxFileCount != 0)
|
||||
{
|
||||
ha->pHetTable = CreateHetTable(ha->dwFileTableSize, 0, 0x40, NULL);
|
||||
if(ha->pHetTable == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Create initial hash table
|
||||
if(dwErrCode == ERROR_SUCCESS && dwHashTableSize != 0)
|
||||
{
|
||||
dwErrCode = CreateHashTable(ha, dwHashTableSize);
|
||||
}
|
||||
|
||||
// Create initial file table
|
||||
if(dwErrCode == ERROR_SUCCESS && ha->dwMaxFileCount != 0)
|
||||
{
|
||||
dwErrCode = CreateFileTable(ha, ha->dwMaxFileCount);
|
||||
}
|
||||
|
||||
// Cleanup : If an error, delete all buffers and return
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
FreeArchiveHandle(ha);
|
||||
SetLastError(dwErrCode);
|
||||
ha = NULL;
|
||||
}
|
||||
|
||||
// Return the values
|
||||
*phMpq = (HANDLE)ha;
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
64
vendor/stormlib-9/src/SFileExtractFile.cpp
vendored
Normal file
64
vendor/stormlib-9/src/SFileExtractFile.cpp
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Simple extracting utility */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
|
||||
{
|
||||
TFileStream * pLocalFile = NULL;
|
||||
HANDLE hMpqFile = NULL;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Open the MPQ file
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile))
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
|
||||
// Create the local file
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
pLocalFile = FileStream_CreateFile(szExtracted, 0);
|
||||
if(pLocalFile == NULL)
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
|
||||
// Copy the file's content
|
||||
while(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
char szBuffer[0x1000];
|
||||
DWORD dwTransferred = 0;
|
||||
|
||||
// dwTransferred is only set to nonzero if something has been read.
|
||||
// dwErrCode can be ERROR_SUCCESS or ERROR_HANDLE_EOF
|
||||
if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL))
|
||||
dwErrCode = GetLastError();
|
||||
if(dwErrCode == ERROR_HANDLE_EOF)
|
||||
dwErrCode = ERROR_SUCCESS;
|
||||
if(dwTransferred == 0)
|
||||
break;
|
||||
|
||||
// If something has been actually read, write it
|
||||
if(!FileStream_Write(pLocalFile, NULL, szBuffer, dwTransferred))
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
|
||||
// Close the files
|
||||
if(hMpqFile != NULL)
|
||||
SFileCloseFile(hMpqFile);
|
||||
if(pLocalFile != NULL)
|
||||
FileStream_Close(pLocalFile);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
484
vendor/stormlib-9/src/SFileFindFile.cpp
vendored
Normal file
484
vendor/stormlib-9/src/SFileFindFile.cpp
vendored
Normal file
@ -0,0 +1,484 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* A module for file searching within MPQs */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private structure used for file search (search handle)
|
||||
|
||||
// Used by searching in MPQ archives
|
||||
struct TMPQSearch
|
||||
{
|
||||
TMPQArchive * ha; // Handle to MPQ, where the search runs
|
||||
TFileEntry ** pSearchTable; // Table for files that have been already found
|
||||
DWORD dwSearchTableItems; // Number of items in the search table
|
||||
DWORD dwNextIndex; // Next file index to be checked
|
||||
DWORD dwFlagMask; // For checking flag mask
|
||||
char szSearchMask[1]; // Search mask (variable length)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static TMPQSearch * IsValidSearchHandle(HANDLE hFind)
|
||||
{
|
||||
TMPQSearch * hs = (TMPQSearch *)hFind;
|
||||
|
||||
if(hs != NULL && IsValidMpqHandle(hs->ha))
|
||||
return hs;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SFileCheckWildCard(const char * szString, const char * szWildCard)
|
||||
{
|
||||
const char * szWildCardPtr;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// If there is '?' in the wildcard, we skip one char
|
||||
while(szWildCard[0] == '?')
|
||||
{
|
||||
if(szString[0] == 0)
|
||||
return false;
|
||||
|
||||
szWildCard++;
|
||||
szString++;
|
||||
}
|
||||
|
||||
// Handle '*'
|
||||
szWildCardPtr = szWildCard;
|
||||
if(szWildCardPtr[0] != 0)
|
||||
{
|
||||
if(szWildCardPtr[0] == '*')
|
||||
{
|
||||
while(szWildCardPtr[0] == '*')
|
||||
szWildCardPtr++;
|
||||
|
||||
if(szWildCardPtr[0] == 0)
|
||||
return true;
|
||||
|
||||
if(AsciiToUpperTable[szWildCardPtr[0]] == AsciiToUpperTable[szString[0]])
|
||||
{
|
||||
if(SFileCheckWildCard(szString, szWildCardPtr))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(AsciiToUpperTable[szWildCardPtr[0]] != AsciiToUpperTable[szString[0]])
|
||||
return false;
|
||||
|
||||
szWildCard = szWildCardPtr + 1;
|
||||
}
|
||||
|
||||
if(szString[0] == 0)
|
||||
return false;
|
||||
szString++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (szString[0] == 0) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD GetSearchTableItems(TMPQArchive * ha)
|
||||
{
|
||||
DWORD dwMergeItems = 0;
|
||||
|
||||
// Loop over all patches
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Append the number of files
|
||||
dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwEntryCount
|
||||
: ha->pHeader->dwBlockTableSize;
|
||||
// Move to the patched archive
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
// Return the double size of number of items
|
||||
return (dwMergeItems | 1);
|
||||
}
|
||||
|
||||
static bool FileWasFoundBefore(
|
||||
TMPQArchive * ha,
|
||||
TMPQSearch * hs,
|
||||
TFileEntry * pFileEntry)
|
||||
{
|
||||
TFileEntry * pEntry;
|
||||
char * szRealFileName = pFileEntry->szFileName;
|
||||
DWORD dwStartIndex;
|
||||
DWORD dwNameHash;
|
||||
DWORD dwIndex;
|
||||
|
||||
if(hs->pSearchTable != NULL && szRealFileName != NULL)
|
||||
{
|
||||
// If we are in patch MPQ, we check if patch prefix matches
|
||||
// and then trim the patch prefix
|
||||
if(ha->pPatchPrefix != NULL)
|
||||
{
|
||||
// If the patch prefix doesn't fit, we pretend that the file
|
||||
// was there before and it will be skipped
|
||||
if(_strnicmp(szRealFileName, ha->pPatchPrefix->szPatchPrefix, ha->pPatchPrefix->nLength))
|
||||
return true;
|
||||
|
||||
szRealFileName += ha->pPatchPrefix->nLength;
|
||||
}
|
||||
|
||||
// Calculate the hash to the table
|
||||
dwNameHash = ha->pfnHashString(szRealFileName, MPQ_HASH_NAME_A);
|
||||
dwStartIndex = dwIndex = (dwNameHash % hs->dwSearchTableItems);
|
||||
|
||||
// The file might have been found before
|
||||
// only if this is not the first MPQ being searched
|
||||
if(ha->haBase != NULL)
|
||||
{
|
||||
// Enumerate all entries in the search table
|
||||
for(;;)
|
||||
{
|
||||
// Get the file entry at that position
|
||||
pEntry = hs->pSearchTable[dwIndex];
|
||||
if(pEntry == NULL)
|
||||
break;
|
||||
|
||||
if(pEntry->szFileName != NULL)
|
||||
{
|
||||
// Does the name match?
|
||||
if(!_stricmp(pEntry->szFileName, szRealFileName))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move to the next entry
|
||||
dwIndex = (dwIndex + 1) % hs->dwSearchTableItems;
|
||||
if(dwIndex == dwStartIndex)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Put the entry to the table for later use
|
||||
hs->pSearchTable[dwIndex] = pFileEntry;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
|
||||
{
|
||||
TFileEntry * pPatchEntry = pFileEntry;
|
||||
TFileEntry * pTempEntry;
|
||||
char szFileName[MAX_PATH+1];
|
||||
|
||||
// Can't find patch entry for a file that doesn't have name
|
||||
if(pFileEntry->szFileName != NULL && pFileEntry->szFileName[0] != 0)
|
||||
{
|
||||
// Go while there are patches
|
||||
while(ha->haPatch != NULL)
|
||||
{
|
||||
// Move to the patch archive
|
||||
ha = ha->haPatch;
|
||||
szFileName[0] = 0;
|
||||
|
||||
// Prepare the prefix for the file name
|
||||
if(ha->pPatchPrefix && ha->pPatchPrefix->nLength)
|
||||
StringCopy(szFileName, _countof(szFileName), ha->pPatchPrefix->szPatchPrefix);
|
||||
StringCat(szFileName, _countof(szFileName), pFileEntry->szFileName);
|
||||
|
||||
// Try to find the file there
|
||||
pTempEntry = GetFileEntryExact(ha, szFileName, 0, NULL);
|
||||
if(pTempEntry != NULL)
|
||||
pPatchEntry = pTempEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the found patch entry
|
||||
return pPatchEntry;
|
||||
}
|
||||
|
||||
static bool DoMPQSearch_FileEntry(
|
||||
TMPQSearch * hs,
|
||||
SFILE_FIND_DATA * lpFindFileData,
|
||||
TMPQArchive * ha,
|
||||
TMPQHash * pHashEntry,
|
||||
TFileEntry * pFileEntry)
|
||||
{
|
||||
TFileEntry * pPatchEntry;
|
||||
HANDLE hFile = NULL;
|
||||
const char * szFileName;
|
||||
size_t nGlobalPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0;
|
||||
DWORD dwBlockIndex;
|
||||
char szNameBuff[MAX_PATH];
|
||||
|
||||
// Is it a file but not a patch file?
|
||||
if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
|
||||
{
|
||||
// Ignore fake files which are not compressed but have size higher than the archive
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
|
||||
return false;
|
||||
|
||||
// Now we have to check if this file was not enumerated before
|
||||
if(!FileWasFoundBefore(ha, hs, pFileEntry))
|
||||
{
|
||||
size_t nPrefixLength = nGlobalPrefixLength;
|
||||
|
||||
// if(pFileEntry != NULL && !_stricmp(pFileEntry->szFileName, "TriggerLibs\\NativeLib.galaxy"))
|
||||
// DebugBreak();
|
||||
|
||||
// Find a patch to this file
|
||||
// Note: This either succeeds or returns pFileEntry
|
||||
pPatchEntry = FindPatchEntry(ha, pFileEntry);
|
||||
|
||||
// Prepare the block index
|
||||
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
|
||||
|
||||
// Get the file name. If it's not known, we will create pseudo-name
|
||||
szFileName = pFileEntry->szFileName;
|
||||
if(szFileName == NULL)
|
||||
{
|
||||
// Open the file by its pseudo-name.
|
||||
StringCreatePseudoFileName(szNameBuff, _countof(szNameBuff), dwBlockIndex, "xxx");
|
||||
if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
|
||||
{
|
||||
SFileGetFileName(hFile, szNameBuff);
|
||||
SFileCloseFile(hFile);
|
||||
szFileName = szNameBuff;
|
||||
nPrefixLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If the file name is still NULL, we cannot include the file to search results
|
||||
if(szFileName != NULL)
|
||||
{
|
||||
// Check the file name against the wildcard
|
||||
if(SFileCheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
|
||||
{
|
||||
// Fill the found entry. hash entry and block index are taken from the base MPQ
|
||||
lpFindFileData->dwHashIndex = HASH_ENTRY_FREE;
|
||||
lpFindFileData->dwBlockIndex = dwBlockIndex;
|
||||
lpFindFileData->dwFileSize = pPatchEntry->dwFileSize;
|
||||
lpFindFileData->dwFileFlags = pPatchEntry->dwFlags;
|
||||
lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize;
|
||||
lpFindFileData->lcLocale = 0; // pPatchEntry->lcFileLocale;
|
||||
|
||||
// Fill the filetime
|
||||
lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32);
|
||||
lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime);
|
||||
|
||||
// Fill-in the entries from hash table entry, if given
|
||||
if(pHashEntry != NULL)
|
||||
{
|
||||
lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable);
|
||||
lpFindFileData->lcLocale = SFILE_MAKE_LCID(pHashEntry->Locale, pHashEntry->Platform);
|
||||
}
|
||||
|
||||
// Fill the file name and plain file name
|
||||
StringCopy(lpFindFileData->cFileName, _countof(lpFindFileData->cFileName), szFileName + nPrefixLength);
|
||||
lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Either not a valid item or was found before
|
||||
return false;
|
||||
}
|
||||
|
||||
static DWORD DoMPQSearch_HashTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha)
|
||||
{
|
||||
TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
TMPQHash * pHash;
|
||||
|
||||
// Parse the file table
|
||||
for(pHash = ha->pHashTable + hs->dwNextIndex; pHash < pHashTableEnd; pHash++)
|
||||
{
|
||||
// Increment the next index for subsequent search
|
||||
hs->dwNextIndex++;
|
||||
|
||||
// Does this hash table entry point to a proper block table entry?
|
||||
if(IsValidHashEntry(ha, pHash))
|
||||
{
|
||||
// Check if this file entry should be included in the search result
|
||||
if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + MPQ_BLOCK_INDEX(pHash)))
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// No more files
|
||||
return ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
static DWORD DoMPQSearch_FileTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
|
||||
// Parse the file table
|
||||
for(pFileEntry = ha->pFileTable + hs->dwNextIndex; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Increment the next index for subsequent search
|
||||
hs->dwNextIndex++;
|
||||
|
||||
// Check if this file entry should be included in the search result
|
||||
if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, NULL, pFileEntry))
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// No more files
|
||||
return ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
// Performs one MPQ search
|
||||
static DWORD DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQArchive * ha = hs->ha;
|
||||
DWORD dwErrCode;
|
||||
|
||||
// Start searching with base MPQ
|
||||
while(ha != NULL)
|
||||
{
|
||||
// If the archive has hash table, we need to use hash table
|
||||
// in order to catch hash table index and file locale.
|
||||
// Note: If multiple hash table entries, point to the same block entry,
|
||||
// we need, to report them all
|
||||
dwErrCode = (ha->pHashTable != NULL) ? DoMPQSearch_HashTable(hs, lpFindFileData, ha)
|
||||
: DoMPQSearch_FileTable(hs, lpFindFileData, ha);
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// If there is no more patches in the chain, stop it.
|
||||
// This also keeps hs->ha non-NULL, which is required
|
||||
// for freeing the handle later
|
||||
if(ha->haPatch == NULL)
|
||||
break;
|
||||
|
||||
// Move to the next patch in the patch chain
|
||||
hs->ha = ha = ha->haPatch;
|
||||
hs->dwNextIndex = 0;
|
||||
}
|
||||
|
||||
// No more files found, return error
|
||||
return ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
static void FreeMPQSearch(TMPQSearch *& hs)
|
||||
{
|
||||
if(hs != NULL)
|
||||
{
|
||||
if(hs->pSearchTable != NULL)
|
||||
STORM_FREE(hs->pSearchTable);
|
||||
STORM_FREE(hs);
|
||||
hs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQSearch * hs = NULL;
|
||||
size_t nSize = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Check for the valid parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
dwErrCode = ERROR_INVALID_HANDLE;
|
||||
if(szMask == NULL || lpFindFileData == NULL)
|
||||
dwErrCode = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Include the listfile into the MPQ's internal listfile
|
||||
// Note that if the listfile name is NULL, do nothing because the
|
||||
// internal listfile is always included.
|
||||
if(dwErrCode == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
|
||||
dwErrCode = SFileAddListFile((HANDLE)ha, szListFile);
|
||||
|
||||
// Allocate the structure for MPQ search
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
|
||||
if((hs = (TMPQSearch *)STORM_ALLOC(char, nSize)) == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Perform the first search
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
memset(hs, 0, sizeof(TMPQSearch));
|
||||
strcpy(hs->szSearchMask, szMask);
|
||||
hs->dwFlagMask = MPQ_FILE_EXISTS;
|
||||
hs->ha = ha;
|
||||
|
||||
// If the archive is patched archive, we have to create a merge table
|
||||
// to prevent files being repeated
|
||||
if(ha->haPatch != NULL)
|
||||
{
|
||||
hs->dwSearchTableItems = GetSearchTableItems(ha);
|
||||
hs->pSearchTable = STORM_ALLOC(TFileEntry *, hs->dwSearchTableItems);
|
||||
hs->dwFlagMask = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE;
|
||||
if(hs->pSearchTable != NULL)
|
||||
memset(hs->pSearchTable, 0, hs->dwSearchTableItems * sizeof(TFileEntry *));
|
||||
else
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform first item searching
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = DoMPQSearch(hs, lpFindFileData);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQSearch(hs);
|
||||
SetLastError(dwErrCode);
|
||||
}
|
||||
|
||||
// Return the result value
|
||||
return (HANDLE)hs;
|
||||
}
|
||||
|
||||
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQSearch * hs = IsValidSearchHandle(hFind);
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters
|
||||
if(hs == NULL)
|
||||
dwErrCode = ERROR_INVALID_HANDLE;
|
||||
if(lpFindFileData == NULL)
|
||||
dwErrCode = ERROR_INVALID_PARAMETER;
|
||||
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
dwErrCode = DoMPQSearch(hs, lpFindFileData);
|
||||
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
bool WINAPI SFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TMPQSearch * hs = IsValidSearchHandle(hFind);
|
||||
|
||||
// Check the parameters
|
||||
if(hs == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeMPQSearch(hs);
|
||||
return true;
|
||||
}
|
||||
623
vendor/stormlib-9/src/SFileGetFileInfo.cpp
vendored
Normal file
623
vendor/stormlib-9/src/SFileGetFileInfo.cpp
vendored
Normal file
@ -0,0 +1,623 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileGetFileInfo.cpp Copyright (c) Ladislav Zezula 2013 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 30.11.13 1.00 Lad The first version of SFileGetFileInfo.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static DWORD GetMpqFileCount(TMPQArchive * ha)
|
||||
{
|
||||
TFileEntry * pFileTableEnd;
|
||||
TFileEntry * pFileEntry;
|
||||
DWORD dwFileCount = 0;
|
||||
|
||||
// Go through all open MPQs, including patches
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Only count files that are not patch files
|
||||
pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// If the file is patch file and this is not primary archive, skip it
|
||||
// BUGBUG: This errorneously counts non-patch files that are in both
|
||||
// base MPQ and in patches, and increases the number of files by cca 50%
|
||||
if((pFileEntry->dwFlags & (MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE)) == MPQ_FILE_EXISTS)
|
||||
dwFileCount++;
|
||||
}
|
||||
|
||||
// Move to the next patch archive
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
return dwFileCount;
|
||||
}
|
||||
|
||||
static bool GetInfo_ReturnError(DWORD dwErrCode)
|
||||
{
|
||||
SetLastError(dwErrCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool GetInfo_BufferCheck(void * pvFileInfo, DWORD cbFileInfo, DWORD cbData, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
// Give the length needed to store the info
|
||||
if(pcbLengthNeeded != NULL)
|
||||
pcbLengthNeeded[0] = cbData;
|
||||
|
||||
// Check for sufficient buffer
|
||||
if(cbData > cbFileInfo)
|
||||
return GetInfo_ReturnError(ERROR_INSUFFICIENT_BUFFER);
|
||||
|
||||
// If the buffer size is sufficient, check for valid user buffer
|
||||
if(pvFileInfo == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
// Buffers and sizes are OK, we are ready to proceed file copying
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetInfo(void * pvFileInfo, DWORD cbFileInfo, const void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
// Verify the input parameter
|
||||
if(pvData == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
// Verify buffer pointer and buffer size
|
||||
if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded))
|
||||
return false;
|
||||
|
||||
// Copy the data to the caller-supplied buffer
|
||||
memcpy(pvFileInfo, pvData, cbData);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetInfo_Allocated(void * pvFileInfo, DWORD cbFileInfo, void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
bool bResult;
|
||||
|
||||
// Verify the input parameter
|
||||
if(pvData == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
// Verify buffer pointer and buffer size
|
||||
if((bResult = GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) != false)
|
||||
memcpy(pvFileInfo, pvData, cbData);
|
||||
|
||||
// Copy the data to the user buffer
|
||||
STORM_FREE(pvData);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
static bool GetInfo_TablePointer(void * pvFileInfo, DWORD cbFileInfo, void * pvTablePointer, SFileInfoClass InfoClass, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
// Verify buffer pointer and buffer size
|
||||
if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, sizeof(void *), pcbLengthNeeded))
|
||||
{
|
||||
SFileFreeFileInfo(pvTablePointer, InfoClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The user buffer receives pointer to the table.
|
||||
// When done, the caller needs to call SFileFreeFileInfo on it
|
||||
*(void **)pvFileInfo = pvTablePointer;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetInfo_ReadFromFile(void * pvFileInfo, DWORD cbFileInfo, TFileStream * pStream, ULONGLONG ByteOffset, DWORD cbData, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
// Verify buffer pointer and buffer size
|
||||
if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded))
|
||||
return false;
|
||||
|
||||
return FileStream_Read(pStream, &ByteOffset, pvFileInfo, cbData);
|
||||
}
|
||||
|
||||
static bool GetInfo_FileEntry(void * pvFileInfo, DWORD cbFileInfo, TFileEntry * pFileEntry, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
LPBYTE pbFileInfo = (LPBYTE)pvFileInfo;
|
||||
DWORD cbSrcFileInfo = sizeof(TFileEntry);
|
||||
DWORD cbFileName = 1;
|
||||
|
||||
// The file name belongs to the file entry
|
||||
if(pFileEntry->szFileName)
|
||||
cbFileName = (DWORD)strlen(pFileEntry->szFileName) + 1;
|
||||
cbSrcFileInfo += cbFileName;
|
||||
|
||||
// Verify buffer pointer and buffer size
|
||||
if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbSrcFileInfo, pcbLengthNeeded))
|
||||
return false;
|
||||
|
||||
// Copy the file entry
|
||||
memcpy(pbFileInfo, pFileEntry, sizeof(TFileEntry));
|
||||
pbFileInfo += sizeof(TFileEntry);
|
||||
pbFileInfo[0] = 0;
|
||||
|
||||
// Copy the file name
|
||||
if(pFileEntry->szFileName)
|
||||
memcpy(pbFileInfo, pFileEntry->szFileName, cbFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetInfo_PatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
TMPQFile * hfTemp;
|
||||
LPCTSTR szPatchName;
|
||||
LPTSTR szFileInfo = (LPTSTR)pvFileInfo;
|
||||
size_t cchCharsNeeded = 1;
|
||||
size_t nLength;
|
||||
|
||||
// Patch chain is only supported on MPQ files. Local files are not supported.
|
||||
if(hf->pStream != NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
// Calculate the necessary length of the multi-string
|
||||
for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch)
|
||||
cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1;
|
||||
|
||||
// Verify whether the caller gave us valid buffer with enough size
|
||||
if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, (DWORD)(cchCharsNeeded * sizeof(TCHAR)), pcbLengthNeeded))
|
||||
return false;
|
||||
|
||||
// Copy each patch name
|
||||
for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch)
|
||||
{
|
||||
// Get the file name and its length
|
||||
szPatchName = FileStream_GetFileName(hfTemp->ha->pStream);
|
||||
nLength = _tcslen(szPatchName) + 1;
|
||||
|
||||
// Copy the file name
|
||||
memcpy(szFileInfo, szPatchName, nLength * sizeof(TCHAR));
|
||||
szFileInfo += nLength;
|
||||
}
|
||||
|
||||
// Make it multi-string
|
||||
szFileInfo[0] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retrieves an information about an archive or about a file within the archive
|
||||
//
|
||||
// hMpqOrFile - Handle to an MPQ archive or to a file
|
||||
// InfoClass - Information to obtain
|
||||
// pvFileInfo - Pointer to buffer to store the information
|
||||
// cbFileInfo - Size of the buffer pointed by pvFileInfo
|
||||
// pcbLengthNeeded - Receives number of bytes necessary to store the information
|
||||
|
||||
bool WINAPI SFileGetFileInfo(
|
||||
HANDLE hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
void * pvFileInfo,
|
||||
DWORD cbFileInfo,
|
||||
LPDWORD pcbLengthNeeded)
|
||||
{
|
||||
MPQ_SIGNATURE_INFO SignatureInfo;
|
||||
const TCHAR * szSrcFileInfo;
|
||||
TMPQArchive * ha = NULL;
|
||||
TFileEntry * pFileEntry = NULL;
|
||||
TMPQHeader * pHeader = NULL;
|
||||
ULONGLONG Int64Value = 0;
|
||||
ULONGLONG ByteOffset;
|
||||
TMPQFile * hf = NULL;
|
||||
void * pvSrcFileInfo = NULL;
|
||||
DWORD cbSrcFileInfo = 0;
|
||||
DWORD dwInt32Value = 0;
|
||||
|
||||
// Validate archive/file handle
|
||||
if((int)InfoClass <= (int)SFileMpqFlags)
|
||||
{
|
||||
if((ha = IsValidMpqHandle(hMpqOrFile)) == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_HANDLE);
|
||||
pHeader = ha->pHeader;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((hf = IsValidFileHandle(hMpqOrFile)) == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_HANDLE);
|
||||
pFileEntry = hf->pFileEntry;
|
||||
}
|
||||
|
||||
// Return info-class-specific data
|
||||
switch(InfoClass)
|
||||
{
|
||||
case SFileMpqFileName:
|
||||
szSrcFileInfo = FileStream_GetFileName(ha->pStream);
|
||||
cbSrcFileInfo = (DWORD)((_tcslen(szSrcFileInfo) + 1) * sizeof(TCHAR));
|
||||
return GetInfo(pvFileInfo, cbFileInfo, szSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqStreamBitmap:
|
||||
return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqUserDataOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->UserDataPos, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqUserDataHeader:
|
||||
if(ha->pUserData == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos, sizeof(TMPQUserData), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqUserData:
|
||||
if(ha->pUserData == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos + sizeof(TMPQUserData), ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHeaderOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->MpqPos, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHeaderSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHeaderSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHeader:
|
||||
return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->MpqPos, pHeader->dwHeaderSize, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHetTableOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHetTableSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHetHeader:
|
||||
pvSrcFileInfo = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
|
||||
if(pvSrcFileInfo == NULL)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, sizeof(TMPQHetHeader), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHetTable:
|
||||
if((pvSrcFileInfo = LoadHetTable(ha)) == NULL)
|
||||
return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBetTableOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBetTableSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBetHeader:
|
||||
|
||||
// Retrieve the table and its size
|
||||
pvSrcFileInfo = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
|
||||
if(pvSrcFileInfo == NULL)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
cbSrcFileInfo = sizeof(TMPQBetHeader) + ((TMPQBetHeader *)pvSrcFileInfo)->dwFlagCount * sizeof(DWORD);
|
||||
|
||||
// It is allowed for the caller to only require BET header
|
||||
if(cbFileInfo == sizeof(TMPQBetHeader))
|
||||
cbSrcFileInfo = sizeof(TMPQBetHeader);
|
||||
return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBetTable:
|
||||
if((pvSrcFileInfo = LoadBetTable(ha)) == NULL)
|
||||
return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHashTableOffset:
|
||||
Int64Value = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHashTableSize64:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HashTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHashTableSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHashTableSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHashTable:
|
||||
cbSrcFileInfo = pHeader->dwHashTableSize * sizeof(TMPQHash);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, ha->pHashTable, cbSrcFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBlockTableOffset:
|
||||
Int64Value = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBlockTableSize64:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBlockTableSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwBlockTableSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqBlockTable:
|
||||
ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos));
|
||||
if(ByteOffset >= ha->FileSize)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
cbSrcFileInfo = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
|
||||
pvSrcFileInfo = LoadBlockTable(ha, true);
|
||||
return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHiBlockTableOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHiBlockTableSize64:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqHiBlockTable:
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
|
||||
case SFileMpqSignatures:
|
||||
if(!QueryMpqSignatureInfo(ha, &SignatureInfo))
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.SignatureTypes, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqStrongSignatureOffset:
|
||||
if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.EndMpqData, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqStrongSignatureSize:
|
||||
if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4;
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqStrongSignature:
|
||||
if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, SignatureInfo.Signature, MPQ_STRONG_SIGNATURE_SIZE + 4, pcbLengthNeeded);
|
||||
|
||||
case SFileMpqArchiveSize64:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->ArchiveSize64, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqArchiveSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwArchiveSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqMaxFileCount:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->dwMaxFileCount, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqFileTableSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFileTableSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqSectorSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->dwSectorSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqNumberOfFiles:
|
||||
dwInt32Value = GetMpqFileCount(ha);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqRawChunkSize:
|
||||
if(pHeader->dwRawChunkSize == 0)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwRawChunkSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqStreamFlags:
|
||||
FileStream_GetFlags(ha->pStream, &dwInt32Value);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileMpqFlags:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFlags, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoPatchChain:
|
||||
return GetInfo_PatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded);
|
||||
|
||||
case SFileInfoFileEntry:
|
||||
if(pFileEntry == NULL)
|
||||
return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
|
||||
return GetInfo_FileEntry(pvFileInfo, cbFileInfo, pFileEntry, pcbLengthNeeded);
|
||||
|
||||
case SFileInfoHashEntry:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, hf->pHashEntry, sizeof(TMPQHash), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoHashIndex:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &hf->dwHashIndex, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoNameHash1:
|
||||
if(hf->pHashEntry == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoNameHash2:
|
||||
if(hf->pHashEntry == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoNameHash3:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoLocale:
|
||||
if(hf->pHashEntry == NULL)
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
dwInt32Value = SFILE_MAKE_LCID(hf->pHashEntry->Locale, hf->pHashEntry->Platform);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoFileIndex:
|
||||
dwInt32Value = (DWORD)(pFileEntry - hf->ha->pFileTable);
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoByteOffset:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->ByteOffset, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoFileTime:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileTime, sizeof(ULONGLONG), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoFileSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFileSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoCompressedSize:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwCmpSize, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoFlags:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFlags, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoEncryptionKey:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &hf->dwFileKey, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoEncryptionKeyRaw:
|
||||
dwInt32Value = hf->dwFileKey;
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_KEY_V2)
|
||||
dwInt32Value = (dwInt32Value ^ pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos;
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
|
||||
|
||||
case SFileInfoCRC32:
|
||||
return GetInfo(pvFileInfo, cbFileInfo, &hf->pFileEntry->dwCrc32, sizeof(DWORD), pcbLengthNeeded);
|
||||
default:
|
||||
// Invalid info class
|
||||
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass)
|
||||
{
|
||||
switch(InfoClass)
|
||||
{
|
||||
case SFileMpqHetTable:
|
||||
FreeHetTable((TMPQHetTable *)pvFileInfo);
|
||||
return true;
|
||||
|
||||
case SFileMpqBetTable:
|
||||
FreeBetTable((TMPQBetTable *)pvFileInfo);
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tries to retrieve the file name
|
||||
|
||||
struct TFileHeader2Ext
|
||||
{
|
||||
DWORD dwOffset00Data; // Required data at offset 00 (32-bits)
|
||||
DWORD dwOffset00Mask; // Mask for data at offset 00 (32 bits). 0 = data are ignored
|
||||
DWORD dwOffset04Data; // Required data at offset 04 (32-bits)
|
||||
DWORD dwOffset04Mask; // Mask for data at offset 04 (32 bits). 0 = data are ignored
|
||||
const char * szExt; // Supplied extension, if the condition is true
|
||||
};
|
||||
|
||||
static TFileHeader2Ext data2ext[] =
|
||||
{
|
||||
{0x00005A4D, 0x0000FFFF, 0x00000000, 0x00000000, "exe"}, // EXE files
|
||||
{0x00000006, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, "dc6"}, // EXE files
|
||||
{0x1A51504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mpq"}, // MPQ archive header ID ('MPQ\x1A')
|
||||
{0x46464952, 0xFFFFFFFF, 0x00000000, 0x00000000, "wav"}, // WAVE header 'RIFF'
|
||||
{0x324B4D53, 0xFFFFFFFF, 0x00000000, 0x00000000, "smk"}, // Old "Smacker Video" files 'SMK2'
|
||||
{0x694B4942, 0xFFFFFFFF, 0x00000000, 0x00000000, "bik"}, // Bink video files (new)
|
||||
{0x0801050A, 0xFFFFFFFF, 0x00000000, 0x00000000, "pcx"}, // PCX images used in Diablo I
|
||||
{0x544E4F46, 0xFFFFFFFF, 0x00000000, 0x00000000, "fnt"}, // Font files used in Diablo II
|
||||
{0x6D74683C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<htm'
|
||||
{0x4D54483C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<HTM
|
||||
{0x216F6F57, 0xFFFFFFFF, 0x00000000, 0x00000000, "tbl"}, // Table files
|
||||
{0x31504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures
|
||||
{0x32504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures (v2)
|
||||
{0x584C444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mdx"}, // MDX files
|
||||
{0x45505954, 0xFFFFFFFF, 0x00000000, 0x00000000, "pud"}, // Warcraft II maps
|
||||
{0x38464947, 0xFFFFFFFF, 0x00000000, 0x00000000, "gif"}, // GIF images 'GIF8'
|
||||
{0x3032444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "m2"}, // WoW ??? .m2
|
||||
{0x43424457, 0xFFFFFFFF, 0x00000000, 0x00000000, "dbc"}, // ??? .dbc
|
||||
{0x47585053, 0xFFFFFFFF, 0x00000000, 0x00000000, "bls"}, // WoW pixel shaders
|
||||
{0xE0FFD8FF, 0xFFFFFFFF, 0x00000000, 0x00000000, "jpg"}, // JPEG image
|
||||
{0x503B4449, 0xFFFFFFFF, 0x3B4C5857, 0xFFFFFFFF, "slk"}, // SLK file (usually starts with "ID;PWXL;N;E")
|
||||
{0x61754C1B, 0xFFFFFFFF, 0x00000000, 0x00000000, "lua"}, // Compiled LUA files
|
||||
{0x20534444, 0xFFFFFFFF, 0x00000000, 0x00000000, "dds"}, // DDS textures
|
||||
{0x43614C66, 0xFFFFFFFF, 0x00000000, 0x00000000, "flac"}, // FLAC sound files
|
||||
{0x0000FBFF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files
|
||||
{0x0000F3FF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files
|
||||
{0x0000F2FF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files
|
||||
{0x00334449, 0x00FFFFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files
|
||||
{0x57334D48, 0xFFFFFFFF, 0x00000000, 0x00000000, "w3x"}, // Warcraft III map files, can also be w3m
|
||||
{0x6F643357, 0xFFFFFFFF, 0x00000000, 0x00000000, "doo"}, // Warcraft III doodad files
|
||||
{0x21453357, 0xFFFFFFFF, 0x00000000, 0x00000000, "w3e"}, // Warcraft III environment files
|
||||
{0x5733504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "wpm"}, // Warcraft III pathing map files
|
||||
{0x21475457, 0xFFFFFFFF, 0x00000000, 0x00000000, "wtg"}, // Warcraft III trigger files
|
||||
{0x00000000, 0x00000000, 0x00000000, 0x00000000, "xxx"}, // Default extension
|
||||
{0, 0, 0, 0, NULL} // Terminator
|
||||
};
|
||||
|
||||
static DWORD CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
|
||||
DWORD FirstBytes[2] = {0, 0}; // The first 4 bytes of the file
|
||||
DWORD dwBytesRead = 0;
|
||||
DWORD dwFilePos; // Saved file position
|
||||
char szPseudoName[20];
|
||||
|
||||
// Read the first 2 DWORDs bytes from the file
|
||||
dwFilePos = SFileSetFilePointer(hFile, 0, NULL, FILE_CURRENT);
|
||||
SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), &dwBytesRead, NULL);
|
||||
SFileSetFilePointer(hFile, dwFilePos, NULL, FILE_BEGIN);
|
||||
|
||||
// If we read at least 8 bytes
|
||||
if(dwBytesRead == sizeof(FirstBytes))
|
||||
{
|
||||
// Make sure that the array is properly BSWAP-ed
|
||||
BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes));
|
||||
|
||||
// Try to guess file extension from those 2 DWORDs
|
||||
for(size_t i = 0; data2ext[i].szExt != NULL; i++)
|
||||
{
|
||||
if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data &&
|
||||
(FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data)
|
||||
{
|
||||
// Format the pseudo-name
|
||||
StringCreatePseudoFileName(szPseudoName, _countof(szPseudoName), (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt);
|
||||
|
||||
// Save the pseudo-name in the file entry as well
|
||||
AllocateFileName(hf->ha, pFileEntry, szPseudoName);
|
||||
|
||||
// If the caller wants to copy the file name, do it
|
||||
if(szFileName != NULL)
|
||||
strcpy(szFileName, szPseudoName);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName)
|
||||
{
|
||||
TMPQFile * hf;
|
||||
DWORD dwErrCode = ERROR_INVALID_HANDLE;
|
||||
|
||||
// Check valid parameters
|
||||
if((hf = IsValidFileHandle(hFile)) != NULL)
|
||||
{
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
|
||||
// For MPQ files, retrieve the file name from the file entry
|
||||
if(hf->pStream == NULL)
|
||||
{
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// If the file name is not there yet, create a pseudo name
|
||||
if(pFileEntry->szFileName == NULL)
|
||||
dwErrCode = CreatePseudoFileName(hFile, pFileEntry, szFileName);
|
||||
|
||||
// Copy the file name to the output buffer, if any
|
||||
if(pFileEntry->szFileName && szFileName)
|
||||
{
|
||||
strcpy(szFileName, pFileEntry->szFileName);
|
||||
dwErrCode = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For local files, copy the file name from the stream
|
||||
else
|
||||
{
|
||||
if(szFileName != NULL)
|
||||
{
|
||||
const TCHAR * szStreamName = FileStream_GetFileName(hf->pStream);
|
||||
StringCopy(szFileName, MAX_PATH, szStreamName);
|
||||
}
|
||||
dwErrCode = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
750
vendor/stormlib-9/src/SFileListFile.cpp
vendored
Normal file
750
vendor/stormlib-9/src/SFileListFile.cpp
vendored
Normal file
@ -0,0 +1,750 @@
|
||||
/*****************************************************************************/
|
||||
/* SListFile.cpp Copyright (c) Ladislav Zezula 2004 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SListFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
#include <assert.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile entry structure
|
||||
|
||||
#define CACHE_BUFFER_SIZE 0x1000 // Size of the cache buffer
|
||||
#define MAX_LISTFILE_SIZE 0x8000000 // Maximum accepted listfile size is 128 MB
|
||||
|
||||
union TListFileHandle
|
||||
{
|
||||
TFileStream * pStream; // Opened local file
|
||||
HANDLE hFile; // Opened MPQ file
|
||||
};
|
||||
|
||||
struct TListFileCache
|
||||
{
|
||||
char * szWildCard; // Self-relative pointer to file mask
|
||||
LPBYTE pBegin; // The begin of the listfile cache
|
||||
LPBYTE pPos; // Current position in the cache
|
||||
LPBYTE pEnd; // The last character in the file cache
|
||||
DWORD dwFlags; // Flags from TMPQArchive
|
||||
|
||||
// char szWildCard[wildcard_length]; // Followed by the name mask (if any)
|
||||
// char szListFile[listfile_length]; // Followed by the listfile (if any)
|
||||
};
|
||||
|
||||
typedef bool (*LOAD_LISTFILE)(TListFileHandle * pHandle, void * pvBuffer, DWORD cbBuffer, LPDWORD pdwBytesRead);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (cache)
|
||||
|
||||
// In SFileFindFile.cll
|
||||
bool SFileCheckWildCard(const char * szString, const char * szWildCard);
|
||||
|
||||
static char * CopyListLine(char * szListLine, const char * szFileName)
|
||||
{
|
||||
// Copy the string
|
||||
while(szFileName[0] != 0)
|
||||
*szListLine++ = *szFileName++;
|
||||
|
||||
// Append the end-of-line
|
||||
*szListLine++ = 0x0D;
|
||||
*szListLine++ = 0x0A;
|
||||
return szListLine;
|
||||
}
|
||||
|
||||
static bool LoadListFile_Stream(TListFileHandle * pHandle, void * pvBuffer, DWORD cbBuffer, LPDWORD pdwBytesRead)
|
||||
{
|
||||
ULONGLONG ByteOffset = 0;
|
||||
bool bResult;
|
||||
|
||||
bResult = FileStream_Read(pHandle->pStream, &ByteOffset, pvBuffer, cbBuffer);
|
||||
if(bResult)
|
||||
*pdwBytesRead = cbBuffer;
|
||||
return bResult;
|
||||
}
|
||||
|
||||
static bool LoadListFile_MPQ(TListFileHandle * pHandle, void * pvBuffer, DWORD cbBuffer, LPDWORD pdwBytesRead)
|
||||
{
|
||||
return SFileReadFile(pHandle->hFile, pvBuffer, cbBuffer, pdwBytesRead, NULL);
|
||||
}
|
||||
|
||||
static bool FreeListFileCache(TListFileCache * pCache)
|
||||
{
|
||||
// Valid parameter check
|
||||
if(pCache != NULL)
|
||||
STORM_FREE(pCache);
|
||||
return true;
|
||||
}
|
||||
|
||||
static TListFileCache * CreateListFileCache(
|
||||
LOAD_LISTFILE PfnLoadFile,
|
||||
TListFileHandle * pHandle,
|
||||
const char * szWildCard,
|
||||
DWORD dwFileSize,
|
||||
DWORD dwMaxSize,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
size_t cchWildCardAligned = 0;
|
||||
size_t cchWildCard = 0;
|
||||
DWORD dwBytesRead = 0;
|
||||
|
||||
// Get the amount of bytes that need to be allocated
|
||||
if(dwFileSize == 0 || dwFileSize > dwMaxSize)
|
||||
return NULL;
|
||||
|
||||
// Append buffer for name mask, if any
|
||||
if(szWildCard != NULL)
|
||||
{
|
||||
cchWildCard = strlen(szWildCard) + 1;
|
||||
cchWildCardAligned = (cchWildCard + 3) & 0xFFFFFFFC;
|
||||
}
|
||||
|
||||
// Allocate cache for one file block
|
||||
pCache = (TListFileCache *)STORM_ALLOC(BYTE, sizeof(TListFileCache) + cchWildCardAligned + dwFileSize + 1);
|
||||
if(pCache != NULL)
|
||||
{
|
||||
// Clear the entire structure
|
||||
memset(pCache, 0, sizeof(TListFileCache) + cchWildCard);
|
||||
pCache->dwFlags = dwFlags;
|
||||
|
||||
// Shall we copy the mask?
|
||||
if(cchWildCard != 0)
|
||||
{
|
||||
pCache->szWildCard = (char *)(pCache + 1);
|
||||
memcpy(pCache->szWildCard, szWildCard, cchWildCard);
|
||||
}
|
||||
|
||||
// Fill-in the rest of the cache pointers
|
||||
pCache->pBegin = (LPBYTE)(pCache + 1) + cchWildCardAligned;
|
||||
|
||||
// Load the entire listfile to the cache
|
||||
PfnLoadFile(pHandle, pCache->pBegin, dwFileSize, &dwBytesRead);
|
||||
if(dwBytesRead != 0)
|
||||
{
|
||||
// Allocate pointers
|
||||
pCache->pPos = pCache->pBegin;
|
||||
pCache->pEnd = pCache->pBegin + dwBytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeListFileCache(pCache);
|
||||
pCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the cache
|
||||
return pCache;
|
||||
}
|
||||
|
||||
static TListFileCache * CreateListFileCache(
|
||||
HANDLE hMpq,
|
||||
const TCHAR * szListFile,
|
||||
const char * szWildCard,
|
||||
DWORD dwMaxSize,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
TListFileHandle ListHandle = {NULL};
|
||||
|
||||
// Put default value to dwMaxSize
|
||||
if(dwMaxSize == 0)
|
||||
dwMaxSize = MAX_LISTFILE_SIZE;
|
||||
|
||||
// Internal listfile: hMPQ must be non NULL and szListFile must be NULL.
|
||||
// We load the MPQ::(listfile) file
|
||||
if(hMpq != NULL && szListFile == NULL)
|
||||
{
|
||||
DWORD dwFileSize = 0;
|
||||
|
||||
// Open the file from the MPQ
|
||||
if(SFileOpenFileEx(hMpq, LISTFILE_NAME, 0, &ListHandle.hFile))
|
||||
{
|
||||
// Get the file size and create the listfile cache
|
||||
dwFileSize = SFileGetFileSize(ListHandle.hFile, NULL);
|
||||
pCache = CreateListFileCache(LoadListFile_MPQ, &ListHandle, szWildCard, dwFileSize, dwMaxSize, dwFlags);
|
||||
|
||||
// Close the MPQ file
|
||||
SFileCloseFile(ListHandle.hFile);
|
||||
}
|
||||
|
||||
// Return the loaded cache
|
||||
return pCache;
|
||||
}
|
||||
|
||||
// External listfile: hMpq must be NULL and szListFile must be non-NULL.
|
||||
// We load the file using TFileStream
|
||||
if(hMpq == NULL && szListFile != NULL)
|
||||
{
|
||||
ULONGLONG FileSize = 0;
|
||||
|
||||
// Open the local file
|
||||
ListHandle.pStream = FileStream_OpenFile(szListFile, STREAM_FLAG_READ_ONLY);
|
||||
if(ListHandle.pStream != NULL)
|
||||
{
|
||||
// Verify the file size
|
||||
FileStream_GetSize(ListHandle.pStream, &FileSize);
|
||||
if(0 < FileSize && FileSize < dwMaxSize)
|
||||
{
|
||||
pCache = CreateListFileCache(LoadListFile_Stream, &ListHandle, szWildCard, (DWORD)FileSize, dwMaxSize, dwFlags);
|
||||
}
|
||||
|
||||
// Close the stream
|
||||
FileStream_Close(ListHandle.pStream);
|
||||
}
|
||||
|
||||
// Return the loaded cache
|
||||
return pCache;
|
||||
}
|
||||
|
||||
// This combination should never happen
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
/*
|
||||
TMPQNameCache * CreateNameCache(HANDLE hListFile, const char * szSearchMask)
|
||||
{
|
||||
TMPQNameCache * pNameCache;
|
||||
char * szCachePointer;
|
||||
size_t cbToAllocate;
|
||||
size_t nMaskLength = 1;
|
||||
DWORD dwBytesRead = 0;
|
||||
DWORD dwFileSize;
|
||||
|
||||
// Get the size of the listfile. Ignore zero or too long ones
|
||||
dwFileSize = SFileGetFileSize(hListFile, NULL);
|
||||
if(dwFileSize == 0 || dwFileSize > MAX_LISTFILE_SIZE)
|
||||
return NULL;
|
||||
|
||||
// Get the length of the search mask
|
||||
if(szSearchMask == NULL)
|
||||
szSearchMask = "*";
|
||||
nMaskLength = strlen(szSearchMask) + 1;
|
||||
|
||||
// Allocate the name cache
|
||||
cbToAllocate = sizeof(TMPQNameCache) + nMaskLength + dwFileSize + 1;
|
||||
pNameCache = (TMPQNameCache *)STORM_ALLOC(BYTE, cbToAllocate);
|
||||
if(pNameCache != NULL)
|
||||
{
|
||||
// Initialize the name cache
|
||||
memset(pNameCache, 0, sizeof(TMPQNameCache));
|
||||
pNameCache->TotalCacheSize = (DWORD)(nMaskLength + dwFileSize + 1);
|
||||
szCachePointer = (char *)(pNameCache + 1);
|
||||
|
||||
// Copy the search mask, if any
|
||||
memcpy(szCachePointer, szSearchMask, nMaskLength);
|
||||
pNameCache->FirstNameOffset = (DWORD)nMaskLength;
|
||||
pNameCache->FreeSpaceOffset = (DWORD)nMaskLength;
|
||||
|
||||
// Read the listfile itself
|
||||
SFileSetFilePointer(hListFile, 0, NULL, FILE_BEGIN);
|
||||
SFileReadFile(hListFile, szCachePointer + nMaskLength, dwFileSize, &dwBytesRead, NULL);
|
||||
|
||||
// If nothing has been read from the listfile, clear the cache
|
||||
if(dwBytesRead == 0)
|
||||
{
|
||||
STORM_FREE(pNameCache);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Move the free space offset
|
||||
pNameCache->FreeSpaceOffset = pNameCache->FirstNameOffset + dwBytesRead + 1;
|
||||
szCachePointer[nMaskLength + dwBytesRead] = 0;
|
||||
}
|
||||
|
||||
return pNameCache;
|
||||
}
|
||||
|
||||
static void FreeNameCache(TMPQNameCache * pNameCache)
|
||||
{
|
||||
if(pNameCache != NULL)
|
||||
STORM_FREE(pNameCache);
|
||||
pNameCache = NULL;
|
||||
}
|
||||
*/
|
||||
#endif // _DEBUG
|
||||
|
||||
static char * ReadListFileLine(TListFileCache * pCache, size_t * PtrLength)
|
||||
{
|
||||
LPBYTE pbLineBegin;
|
||||
LPBYTE pbLineEnd;
|
||||
|
||||
// Skip newlines. Keep spaces and tabs, as they can be a legal part of the file name
|
||||
while(pCache->pPos < pCache->pEnd && (pCache->pPos[0] == 0x0A || pCache->pPos[0] == 0x0D))
|
||||
pCache->pPos++;
|
||||
|
||||
// Set the line begin and end
|
||||
if(pCache->pPos >= pCache->pEnd)
|
||||
return NULL;
|
||||
pbLineBegin = pbLineEnd = pCache->pPos;
|
||||
|
||||
// Find the end of the line
|
||||
while(pCache->pPos < pCache->pEnd && pCache->pPos[0] != 0x0A && pCache->pPos[0] != 0x0D)
|
||||
pCache->pPos++;
|
||||
|
||||
// Remember the end of the line
|
||||
pbLineEnd = pCache->pPos++;
|
||||
pbLineEnd[0] = 0;
|
||||
|
||||
// Give the line to the caller
|
||||
if(PtrLength != NULL)
|
||||
PtrLength[0] = (size_t)(pbLineEnd - pbLineBegin);
|
||||
return (char *)pbLineBegin;
|
||||
}
|
||||
|
||||
static int STORMLIB_CDECL CompareFileNodes(const void * p1, const void * p2)
|
||||
{
|
||||
char * szFileName1 = *(char **)p1;
|
||||
char * szFileName2 = *(char **)p2;
|
||||
|
||||
return _stricmp(szFileName1, szFileName2);
|
||||
}
|
||||
|
||||
static LPBYTE CreateListFile(TMPQArchive * ha, DWORD * pcbListFile)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
char ** SortTable = NULL;
|
||||
char * szListFile = NULL;
|
||||
char * szListLine;
|
||||
size_t nFileNodes = 0;
|
||||
size_t cbListFile = 0;
|
||||
size_t nIndex0;
|
||||
size_t nIndex1;
|
||||
|
||||
// Allocate the table for sorting listfile
|
||||
SortTable = STORM_ALLOC(char*, ha->dwFileTableSize);
|
||||
if(SortTable == NULL)
|
||||
return NULL;
|
||||
|
||||
// Construct the sort table
|
||||
// Note: in MPQs with multiple locale versions of the same file,
|
||||
// this code causes adding multiple listfile entries.
|
||||
// They will get removed after the listfile sorting
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Only take existing items
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->szFileName != NULL)
|
||||
{
|
||||
// Ignore pseudo-names and internal names
|
||||
if(!IsPseudoFileName(pFileEntry->szFileName, NULL) && !IsInternalMpqFileName(pFileEntry->szFileName))
|
||||
{
|
||||
SortTable[nFileNodes++] = pFileEntry->szFileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicities
|
||||
if(nFileNodes > 0)
|
||||
{
|
||||
// Sort the table
|
||||
qsort(SortTable, nFileNodes, sizeof(char *), CompareFileNodes);
|
||||
|
||||
// Count the 0-th item
|
||||
cbListFile += strlen(SortTable[0]) + 2;
|
||||
|
||||
// Walk through the items and only use the ones that are not duplicated
|
||||
for(nIndex0 = 0, nIndex1 = 1; nIndex1 < nFileNodes; nIndex1++)
|
||||
{
|
||||
// If the next file node is different, we will include it to the result listfile
|
||||
if(_stricmp(SortTable[nIndex1], SortTable[nIndex0]) != 0)
|
||||
{
|
||||
cbListFile += strlen(SortTable[nIndex1]) + 2;
|
||||
nIndex0 = nIndex1;
|
||||
}
|
||||
}
|
||||
|
||||
// Now allocate buffer for the entire listfile
|
||||
szListFile = szListLine = STORM_ALLOC(char, cbListFile + 1);
|
||||
if(szListFile != NULL)
|
||||
{
|
||||
// Copy the 0-th item
|
||||
szListLine = CopyListLine(szListLine, SortTable[0]);
|
||||
|
||||
// Walk through the items and only use the ones that are not duplicated
|
||||
for(nIndex0 = 0, nIndex1 = 1; nIndex1 < nFileNodes; nIndex1++)
|
||||
{
|
||||
// If the next file node is different, we will include it to the result listfile
|
||||
if(_stricmp(SortTable[nIndex1], SortTable[nIndex0]) != 0)
|
||||
{
|
||||
// Copy the listfile line
|
||||
szListLine = CopyListLine(szListLine, SortTable[nIndex1]);
|
||||
nIndex0 = nIndex1;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check - does the size match?
|
||||
assert((size_t)(szListLine - szListFile) == cbListFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
szListFile = STORM_ALLOC(char, 1);
|
||||
cbListFile = 0;
|
||||
}
|
||||
|
||||
// Free the sort table
|
||||
STORM_FREE(SortTable);
|
||||
|
||||
// Give away the listfile
|
||||
if(pcbListFile != NULL)
|
||||
*pcbListFile = (DWORD)cbListFile;
|
||||
return (LPBYTE)szListFile;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (listfile nodes)
|
||||
|
||||
// Adds a name into the list of all names. For each locale in the MPQ,
|
||||
// one entry will be created
|
||||
// If the file name is already there, does nothing.
|
||||
static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFileName)
|
||||
{
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQHash * pHashEnd;
|
||||
TMPQHash * pHash;
|
||||
DWORD dwName1;
|
||||
DWORD dwName2;
|
||||
|
||||
// If we have HET table, use that one
|
||||
if(ha->pHetTable != NULL)
|
||||
{
|
||||
pFileEntry = GetFileEntryLocale(ha, szFileName, 0);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// Allocate file name for the file entry
|
||||
AllocateFileName(ha, pFileEntry, szFileName);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// If we have hash table, we use it
|
||||
if(ha->pHashTable != NULL)
|
||||
{
|
||||
// Get the end of the hash table and both names
|
||||
pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
dwName1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
|
||||
dwName2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
|
||||
|
||||
// Some protectors set very high hash table size (0x00400000 items or more)
|
||||
// in order to make this process very slow. We will ignore items
|
||||
// in the hash table that would be beyond the end of the file.
|
||||
// Example MPQ: MPQ_2022_v1_Sniper.scx
|
||||
if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT)
|
||||
pHashEnd = ha->pHashTable + (ha->dwRealHashTableSize / sizeof(TMPQHash));
|
||||
|
||||
// Go through the hash table and put the name in each item that has the same name pair
|
||||
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
|
||||
{
|
||||
if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
|
||||
{
|
||||
// Allocate file name for the file entry
|
||||
AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
|
||||
}
|
||||
}
|
||||
|
||||
// Go while we found something
|
||||
//pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
|
||||
//while(pHash != NULL)
|
||||
//{
|
||||
// // Allocate file name for the file entry
|
||||
// AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
|
||||
|
||||
// // Now find the next language version of the file
|
||||
// pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
//}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// Saves the whole listfile to the MPQ
|
||||
DWORD SListFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
TMPQFile * hf = NULL;
|
||||
LPBYTE pbListFile;
|
||||
DWORD cbListFile = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Only save the listfile if we should do so
|
||||
if(ha->dwFileFlags1 != 0)
|
||||
{
|
||||
// At this point, we expect to have at least one reserved entry in the file table
|
||||
assert(ha->dwFlags & MPQ_FLAG_LISTFILE_NEW);
|
||||
assert(ha->dwReservedFiles > 0);
|
||||
|
||||
// Create the raw data that is to be written to (listfile)
|
||||
// Note: Creating the raw data before the (listfile) has been created in the MPQ
|
||||
// causes that the name of the listfile will not be included in the listfile itself.
|
||||
// That is OK, because (listfile) in Blizzard MPQs does not contain it either.
|
||||
pbListFile = CreateListFile(ha, &cbListFile);
|
||||
if(pbListFile != NULL)
|
||||
{
|
||||
// Determine the real flags for (listfile)
|
||||
if(ha->dwFileFlags1 == MPQ_FILE_DEFAULT_INTERNAL)
|
||||
ha->dwFileFlags1 = GetDefaultSpecialFileFlags(cbListFile, ha->pHeader->wFormatVersion);
|
||||
|
||||
// Create the listfile in the MPQ
|
||||
dwErrCode = SFileAddFile_Init(ha, LISTFILE_NAME,
|
||||
0,
|
||||
cbListFile,
|
||||
LANG_NEUTRAL,
|
||||
ha->dwFileFlags1 | MPQ_FILE_REPLACEEXISTING,
|
||||
&hf);
|
||||
|
||||
// Write the listfile raw data to it
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Write the content of the listfile to the MPQ
|
||||
dwErrCode = SFileAddFile_Write(hf, pbListFile, cbListFile, MPQ_COMPRESSION_ZLIB);
|
||||
SFileAddFile_Finish(hf);
|
||||
}
|
||||
|
||||
// Clear the listfile flags
|
||||
ha->dwFlags &= ~(MPQ_FLAG_LISTFILE_NEW | MPQ_FLAG_LISTFILE_NONE);
|
||||
ha->dwReservedFiles--;
|
||||
|
||||
// Free the listfile buffer
|
||||
STORM_FREE(pbListFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the (listfile) file would be empty, its OK
|
||||
dwErrCode = (cbListFile == 0) ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD SFileAddArbitraryListFile(
|
||||
TMPQArchive * ha,
|
||||
HANDLE hMpq,
|
||||
const TCHAR * szListFile,
|
||||
DWORD dwMaxSize)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
|
||||
// Create the listfile cache for that file
|
||||
pCache = CreateListFileCache(hMpq, szListFile, NULL, dwMaxSize, ha->dwFlags);
|
||||
if(pCache != NULL)
|
||||
{
|
||||
char * szFileName;
|
||||
size_t nLength = 0;
|
||||
|
||||
// Get the next line
|
||||
while((szFileName = ReadListFileLine(pCache, &nLength)) != NULL)
|
||||
{
|
||||
// Add the line to the MPQ
|
||||
if(nLength != 0)
|
||||
SListFileCreateNodeForAllLocales(ha, szFileName);
|
||||
}
|
||||
|
||||
// Delete the cache
|
||||
FreeListFileCache(pCache);
|
||||
}
|
||||
|
||||
return (pCache != NULL) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
static DWORD SFileAddArbitraryListFile(
|
||||
TMPQArchive * ha,
|
||||
const char ** listFileEntries,
|
||||
DWORD dwEntryCount)
|
||||
{
|
||||
if(listFileEntries != NULL && dwEntryCount > 0)
|
||||
{
|
||||
// Get the next line
|
||||
for(DWORD dwListFileNum = 0; dwListFileNum < dwEntryCount; dwListFileNum++)
|
||||
{
|
||||
const char * listFileEntry = listFileEntries[dwListFileNum];
|
||||
if(listFileEntry != NULL)
|
||||
{
|
||||
SListFileCreateNodeForAllLocales(ha, listFileEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (listFileEntries != NULL && dwEntryCount > 0) ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
static DWORD SFileAddInternalListFile(
|
||||
TMPQArchive * ha,
|
||||
HANDLE hMpq)
|
||||
{
|
||||
TMPQHash * pFirstHash;
|
||||
TMPQHash * pHash;
|
||||
LCID lcSaveLocale = g_lcFileLocale;
|
||||
DWORD dwMaxSize = MAX_LISTFILE_SIZE;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// If there is hash table, we need to support multiple listfiles
|
||||
// with different locales (BrooDat.mpq)
|
||||
if(ha->pHashTable != NULL)
|
||||
{
|
||||
// If the archive is a malformed map, ignore too large listfiles
|
||||
if(STORMLIB_TEST_FLAGS(ha->dwFlags, MPQ_FLAG_MALFORMED | MPQ_FLAG_PATCH, MPQ_FLAG_MALFORMED))
|
||||
dwMaxSize = 0x40000;
|
||||
|
||||
pFirstHash = pHash = GetFirstHashEntry(ha, LISTFILE_NAME);
|
||||
while(dwErrCode == ERROR_SUCCESS && pHash != NULL)
|
||||
{
|
||||
// Set the prefered locale to that from list file
|
||||
SFileSetLocale(SFILE_MAKE_LCID(pHash->Locale, pHash->Platform));
|
||||
|
||||
// Add that listfile
|
||||
dwErrCode = SFileAddArbitraryListFile(ha, hMpq, NULL, dwMaxSize);
|
||||
|
||||
// Move to the next hash
|
||||
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
}
|
||||
|
||||
// Restore the original locale
|
||||
SFileSetLocale(lcSaveLocale);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the single listfile
|
||||
dwErrCode = SFileAddArbitraryListFile(ha, hMpq, NULL, dwMaxSize);
|
||||
}
|
||||
|
||||
// Return the result of the operation
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static bool DoListFileSearch(TListFileCache * pCache, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
// Check for the valid search handle
|
||||
if(pCache != NULL)
|
||||
{
|
||||
char * szFileName;
|
||||
size_t nLength = 0;
|
||||
|
||||
// Get the next line
|
||||
while((szFileName = ReadListFileLine(pCache, &nLength)) != NULL)
|
||||
{
|
||||
// Check search mask
|
||||
if(nLength != 0 && SFileCheckWildCard(szFileName, pCache->szWildCard))
|
||||
{
|
||||
if(nLength >= sizeof(lpFindFileData->cFileName))
|
||||
nLength = sizeof(lpFindFileData->cFileName) - 1;
|
||||
|
||||
memcpy(lpFindFileData->cFileName, szFileName, nLength);
|
||||
lpFindFileData->cFileName[nLength] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No more files
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
SetLastError(ERROR_NO_MORE_FILES);
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File functions
|
||||
|
||||
// Adds a listfile into the MPQ archive.
|
||||
DWORD WINAPI SFileAddListFile(HANDLE hMpq, const TCHAR * szListFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Add the listfile for each MPQ in the patch chain
|
||||
while(ha != NULL)
|
||||
{
|
||||
if(szListFile != NULL)
|
||||
dwErrCode = SFileAddArbitraryListFile(ha, NULL, szListFile, MAX_LISTFILE_SIZE);
|
||||
else
|
||||
dwErrCode = SFileAddInternalListFile(ha, hMpq);
|
||||
|
||||
// Also, add three special files to the listfile:
|
||||
// (listfile) itself, (attributes) and (signature)
|
||||
SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME);
|
||||
|
||||
// Move to the next archive in the chain
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
DWORD WINAPI SFileAddListFileEntries(HANDLE hMpq, const char ** listFileEntries, DWORD dwEntryCount)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Add the listfile for each MPQ in the patch chain
|
||||
while(ha != NULL)
|
||||
{
|
||||
if(listFileEntries != NULL && dwEntryCount > 0)
|
||||
dwErrCode = SFileAddArbitraryListFile(ha, listFileEntries, dwEntryCount);
|
||||
else
|
||||
dwErrCode = SFileAddInternalListFile(ha, hMpq);
|
||||
|
||||
// Also, add three special files to the listfile:
|
||||
// (listfile) itself, (attributes) and (signature)
|
||||
SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME);
|
||||
|
||||
// Move to the next archive in the chain
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Enumerating files in listfile
|
||||
|
||||
HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const TCHAR * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
|
||||
// Initialize the structure with zeros
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
|
||||
// Open the local/internal listfile
|
||||
pCache = CreateListFileCache(hMpq, szListFile, szMask, 0, 0);
|
||||
if(pCache != NULL)
|
||||
{
|
||||
if(!DoListFileSearch(pCache, lpFindFileData))
|
||||
{
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
SetLastError(ERROR_NO_MORE_FILES);
|
||||
FreeListFileCache(pCache);
|
||||
pCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the listfile cache as handle
|
||||
return (HANDLE)pCache;
|
||||
}
|
||||
|
||||
bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
return DoListFileSearch((TListFileCache *)hFind, lpFindFileData);
|
||||
}
|
||||
|
||||
bool WINAPI SListFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TListFileCache * pCache = (TListFileCache *)hFind;
|
||||
|
||||
return FreeListFileCache(pCache);
|
||||
}
|
||||
|
||||
700
vendor/stormlib-9/src/SFileOpenArchive.cpp
vendored
Normal file
700
vendor/stormlib-9/src/SFileOpenArchive.cpp
vendored
Normal file
@ -0,0 +1,700 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
|
||||
/* */
|
||||
/* Author : Ladislav Zezula */
|
||||
/* E-mail : ladik@zezula.net */
|
||||
/* WWW : www.zezula.net */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Implementation of archive functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad Created */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
#define HEADER_SEARCH_BUFFER_SIZE 0x1000
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHeaderBuffer)
|
||||
{
|
||||
LPDWORD HeaderInt32 = (LPDWORD)pbHeaderBuffer;
|
||||
LPCTSTR szExtension;
|
||||
|
||||
// Don't do any checks if there is not at least 16 bytes
|
||||
if(cbHeaderBuffer > 0x10)
|
||||
{
|
||||
DWORD DwordValue0 = BSWAP_INT32_UNSIGNED(HeaderInt32[0]);
|
||||
DWORD DwordValue1 = BSWAP_INT32_UNSIGNED(HeaderInt32[1]);
|
||||
DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(HeaderInt32[2]);
|
||||
DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(HeaderInt32[3]);
|
||||
|
||||
// Check maps by extension (Starcraft, Starcraft II). We must do this before
|
||||
// checking actual data, because the "NP_Protect" protector places
|
||||
// fake Warcraft III header into the Starcraft II maps
|
||||
if((szExtension = _tcsrchr(szFileName, _T('.'))) != NULL)
|
||||
{
|
||||
// Check for Starcraft II maps by extension
|
||||
if(!_tcsicmp(szExtension, _T(".s2ma")) || !_tcsicmp(szExtension, _T(".SC2Map")) || !_tcsicmp(szExtension, _T(".SC2Mod")))
|
||||
{
|
||||
return MapTypeStarcraft2;
|
||||
}
|
||||
|
||||
// Check for Starcraft I maps by extension
|
||||
if(!_tcsicmp(szExtension, _T(".scm")) || !_tcsicmp(szExtension, _T(".scx")))
|
||||
{
|
||||
return MapTypeStarcraft;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST'
|
||||
if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C)
|
||||
return MapTypeAviFile;
|
||||
|
||||
// Check for Warcraft III maps
|
||||
if(DwordValue0 == 0x57334D48 && DwordValue1 == 0x00000000)
|
||||
return MapTypeWarcraft3;
|
||||
}
|
||||
|
||||
// MIX files are DLL files that contain MPQ in overlay.
|
||||
// Only Warcraft III is able to load them, so we consider them Warcraft III maps
|
||||
if(cbHeaderBuffer > 0x200 && pbHeaderBuffer[0] == 'M' && pbHeaderBuffer[1] == 'Z')
|
||||
{
|
||||
// Check the value of IMAGE_DOS_HEADER::e_lfanew at offset 0x3C
|
||||
if(0 < HeaderInt32[0x0F] && HeaderInt32[0x0F] < 0x10000)
|
||||
return MapTypeWarcraft3;
|
||||
}
|
||||
|
||||
// No special map type recognized
|
||||
return MapTypeNotRecognized;
|
||||
}
|
||||
|
||||
static bool IsStarcraftBetaArchive(TMPQHeader * pHeader)
|
||||
{
|
||||
// The archive must be version 1, with a standard header size
|
||||
if(pHeader->dwID == ID_MPQ && pHeader->dwHeaderSize == MPQ_HEADER_SIZE_V1)
|
||||
{
|
||||
// Check for known archive sizes
|
||||
return (pHeader->dwArchiveSize == 0x00028FB3 || // patch_rt.mpq
|
||||
pHeader->dwArchiveSize == 0x0351853D || // StarDat.mpq
|
||||
pHeader->dwArchiveSize == 0x0AEC8960); // INSTALL.exe
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TMPQUserData * IsValidMpqUserData(ULONGLONG ByteOffset, ULONGLONG FileSize, void * pvUserData)
|
||||
{
|
||||
TMPQUserData * pUserData;
|
||||
|
||||
// BSWAP the source data and copy them to our buffer
|
||||
BSWAP_ARRAY32_UNSIGNED(pvUserData, sizeof(TMPQUserData));
|
||||
pUserData = (TMPQUserData *)pvUserData;
|
||||
|
||||
// Check the sizes
|
||||
if(pUserData->cbUserDataHeader <= pUserData->cbUserDataSize && pUserData->cbUserDataSize <= pUserData->dwHeaderOffs)
|
||||
{
|
||||
// Move to the position given by the userdata
|
||||
ByteOffset += pUserData->dwHeaderOffs;
|
||||
|
||||
// The MPQ header should be within range of the file size
|
||||
if((ByteOffset + MPQ_HEADER_SIZE_V1) < FileSize)
|
||||
{
|
||||
// Note: We should verify if there is the MPQ header.
|
||||
// However, the header could be at any position below that
|
||||
// that is multiplier of 0x200
|
||||
return (TMPQUserData *)pvUserData;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This function gets the right positions of the hash table and the block table.
|
||||
static DWORD VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
ULONGLONG ByteOffset;
|
||||
//bool bMalformed = (ha->dwFlags & MPQ_FLAG_MALFORMED) ? true : false;
|
||||
|
||||
// Check the begin of HET table
|
||||
if(pHeader->HetTablePos64)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + pHeader->HetTablePos64;
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of BET table
|
||||
if(pHeader->BetTablePos64)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + pHeader->BetTablePos64;
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of hash table
|
||||
if(pHeader->wHashTablePosHi || pHeader->dwHashTablePos)
|
||||
{
|
||||
ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos));
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of block table
|
||||
if(pHeader->wBlockTablePosHi || pHeader->dwBlockTablePos)
|
||||
{
|
||||
ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos));
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of hi-block table
|
||||
//if(pHeader->HiBlockTablePos64 != 0)
|
||||
//{
|
||||
// ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
|
||||
// if(ByteOffset > FileSize)
|
||||
// return ERROR_BAD_FORMAT;
|
||||
//}
|
||||
|
||||
// All OK.
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Support for alternate markers. Call before opening an archive
|
||||
|
||||
#define SFILE_MARKERS_MIN_SIZE (sizeof(DWORD) + sizeof(DWORD) + sizeof(const char *) + sizeof(const char *))
|
||||
|
||||
bool WINAPI SFileSetArchiveMarkers(PSFILE_MARKERS pMarkers)
|
||||
{
|
||||
// Check structure minimum size
|
||||
if(pMarkers == NULL || pMarkers->dwSize < SFILE_MARKERS_MIN_SIZE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that the MPQ cryptography is initialized at this time
|
||||
InitializeMpqCryptography();
|
||||
|
||||
// Remember the marker for MPQ header
|
||||
if(pMarkers->dwSignature != 0)
|
||||
g_dwMpqSignature = pMarkers->dwSignature;
|
||||
|
||||
// Remember the encryption key for hash table
|
||||
if(pMarkers->szHashTableKey != NULL)
|
||||
g_dwHashTableKey = HashString(pMarkers->szHashTableKey, MPQ_HASH_FILE_KEY);
|
||||
|
||||
// Remember the encryption key for block table
|
||||
if(pMarkers->szBlockTableKey != NULL)
|
||||
g_dwBlockTableKey = HashString(pMarkers->szBlockTableKey, MPQ_HASH_FILE_KEY);
|
||||
|
||||
// Succeeded
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetLocale and SFileSetLocale
|
||||
// Set the locale for all newly opened files
|
||||
|
||||
LCID WINAPI SFileGetLocale()
|
||||
{
|
||||
return g_lcFileLocale;
|
||||
}
|
||||
|
||||
LCID WINAPI SFileSetLocale(LCID lcFileLocale)
|
||||
{
|
||||
return (g_lcFileLocale = lcFileLocale);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenArchive
|
||||
//
|
||||
// szFileName - MPQ archive file name to open
|
||||
// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
|
||||
// dwFlags - See MPQ_OPEN_XXX in StormLib.h
|
||||
// phMpq - Pointer to store open archive handle
|
||||
|
||||
bool WINAPI SFileOpenArchive(
|
||||
const TCHAR * szMpqName,
|
||||
DWORD dwPriority,
|
||||
DWORD dwFlags,
|
||||
HANDLE * phMpq)
|
||||
{
|
||||
TMPQUserData * pUserData;
|
||||
TFileStream * pStream = NULL; // Open file stream
|
||||
TMPQArchive * ha = NULL; // Archive handle
|
||||
TFileEntry * pFileEntry;
|
||||
ULONGLONG FileSize = 0; // Size of the file
|
||||
LPBYTE pbHeaderBuffer = NULL; // Buffer for searching MPQ header
|
||||
DWORD dwStreamFlags = (dwFlags & STREAM_FLAGS_MASK);
|
||||
MTYPE MapType = MapTypeNotChecked;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Verify the parameters
|
||||
if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// One time initialization of MPQ cryptography
|
||||
InitializeMpqCryptography();
|
||||
dwPriority = dwPriority;
|
||||
|
||||
// If not forcing MPQ v 1.0, also use file bitmap
|
||||
dwStreamFlags |= (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) ? 0 : STREAM_FLAG_USE_BITMAP;
|
||||
|
||||
// Open the MPQ archive file
|
||||
pStream = FileStream_OpenFile(szMpqName, dwStreamFlags);
|
||||
if(pStream == NULL)
|
||||
return false;
|
||||
|
||||
// Check the file size. There must be at least 0x20 bytes
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_GetSize(pStream, &FileSize);
|
||||
if(FileSize < MPQ_HEADER_SIZE_V1)
|
||||
dwErrCode = ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Allocate the MPQhandle
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Allocate buffer for searching MPQ header
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
pbHeaderBuffer = STORM_ALLOC(BYTE, HEADER_SEARCH_BUFFER_SIZE);
|
||||
if(pbHeaderBuffer == NULL)
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Find the position of MPQ header
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
ULONGLONG ByteOffset = 0;
|
||||
ULONGLONG EndOfSearch = FileSize;
|
||||
DWORD dwStrmFlags = 0;
|
||||
DWORD dwHeaderSize;
|
||||
DWORD dwHeaderID;
|
||||
bool bSearchComplete = false;
|
||||
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS;
|
||||
ha->pfnHashString = HashStringSlash;
|
||||
ha->pStream = pStream;
|
||||
pStream = NULL;
|
||||
|
||||
// Set the archive read only if the stream is read-only
|
||||
FileStream_GetFlags(ha->pStream, &dwStrmFlags);
|
||||
ha->dwFlags |= (dwStrmFlags & STREAM_FLAG_READ_ONLY) ? MPQ_FLAG_READ_ONLY : 0;
|
||||
|
||||
// Also remember if we shall check sector CRCs when reading file
|
||||
ha->dwFlags |= (dwFlags & MPQ_OPEN_CHECK_SECTOR_CRC) ? MPQ_FLAG_CHECK_SECTOR_CRC : 0;
|
||||
|
||||
// Also remember if this MPQ is a patch
|
||||
ha->dwFlags |= (dwFlags & MPQ_OPEN_PATCH) ? MPQ_FLAG_PATCH : 0;
|
||||
|
||||
// Limit the header searching to about 130 MB of data
|
||||
if(EndOfSearch > 0x08000000)
|
||||
EndOfSearch = 0x08000000;
|
||||
if(FileSize < HEADER_SEARCH_BUFFER_SIZE)
|
||||
memset(pbHeaderBuffer, 0, HEADER_SEARCH_BUFFER_SIZE);
|
||||
|
||||
// Find the offset of MPQ header within the file
|
||||
while(bSearchComplete == false && ByteOffset < EndOfSearch)
|
||||
{
|
||||
// Always read at least 0x1000 bytes for performance.
|
||||
// This is what Storm.dll (2002) does.
|
||||
DWORD dwBytesAvailable = HEADER_SEARCH_BUFFER_SIZE;
|
||||
|
||||
// Cut the bytes available, if needed
|
||||
if((FileSize - ByteOffset) < HEADER_SEARCH_BUFFER_SIZE)
|
||||
dwBytesAvailable = (DWORD)(FileSize - ByteOffset);
|
||||
|
||||
// Read the eventual MPQ header
|
||||
if(!FileStream_Read(ha->pStream, &ByteOffset, pbHeaderBuffer, dwBytesAvailable))
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Check whether the file is AVI file or a Warcraft III/Starcraft II map
|
||||
if(MapType == MapTypeNotChecked)
|
||||
{
|
||||
// Do nothing if the file is an AVI file
|
||||
if((MapType = CheckMapType(szMpqName, pbHeaderBuffer, dwBytesAvailable)) == MapTypeAviFile)
|
||||
{
|
||||
dwErrCode = ERROR_AVI_FILE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Search the header buffer
|
||||
for(DWORD dwInBufferOffset = 0; dwInBufferOffset < dwBytesAvailable; dwInBufferOffset += 0x200)
|
||||
{
|
||||
// Copy the data from the potential header buffer to the MPQ header
|
||||
memcpy(ha->HeaderData, pbHeaderBuffer + dwInBufferOffset, sizeof(ha->HeaderData));
|
||||
|
||||
// If there is the MPQ user data, process it
|
||||
// Note that Warcraft III does not check for user data, which is abused by many map protectors
|
||||
dwHeaderID = BSWAP_INT32_UNSIGNED(ha->HeaderData[0]);
|
||||
if(MapType != MapTypeWarcraft3 && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
|
||||
{
|
||||
if(ha->pUserData == NULL && dwHeaderID == ID_MPQ_USERDATA)
|
||||
{
|
||||
// Verify if this looks like a valid user data
|
||||
pUserData = IsValidMpqUserData(ByteOffset, FileSize, ha->HeaderData);
|
||||
if(pUserData != NULL)
|
||||
{
|
||||
// Fill the user data header
|
||||
ha->UserDataPos = ByteOffset;
|
||||
ha->pUserData = &ha->UserData;
|
||||
memcpy(ha->pUserData, pUserData, sizeof(TMPQUserData));
|
||||
|
||||
// Continue searching from that position
|
||||
ByteOffset += ha->pUserData->dwHeaderOffs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There must be MPQ header signature. Note that STORM.dll from Warcraft III actually
|
||||
// tests the MPQ header size. It must be at least 0x20 bytes in order to load it
|
||||
// Abused by Spazzler Map protector. Note that the size check is not present
|
||||
// in Storm.dll v 1.00, so Diablo I code would load the MPQ anyway.
|
||||
dwHeaderSize = BSWAP_INT32_UNSIGNED(ha->HeaderData[1]);
|
||||
if(dwHeaderID == g_dwMpqSignature && dwHeaderSize >= MPQ_HEADER_SIZE_V1)
|
||||
{
|
||||
// Now convert the header to version 4
|
||||
dwErrCode = ConvertMpqHeaderToFormat4(ha, ByteOffset, FileSize, dwFlags, MapType);
|
||||
if(dwErrCode != ERROR_FAKE_MPQ_HEADER)
|
||||
{
|
||||
bSearchComplete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for MPK archives (Longwu Online - MPQ fork)
|
||||
if(MapType == MapTypeNotRecognized && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0 && dwHeaderID == ID_MPK)
|
||||
{
|
||||
// Now convert the MPK header to MPQ Header version 4
|
||||
dwErrCode = ConvertMpkHeaderToFormat4(ha, FileSize, dwFlags);
|
||||
bSearchComplete = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// If searching for the MPQ header is disabled, return an error
|
||||
if(dwFlags & MPQ_OPEN_NO_HEADER_SEARCH)
|
||||
{
|
||||
dwErrCode = ERROR_NOT_SUPPORTED;
|
||||
bSearchComplete = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Move the pointers
|
||||
ByteOffset += 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
// Did we identify one of the supported headers?
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Set the user data position to the MPQ header, if none
|
||||
if(ha->pUserData == NULL)
|
||||
ha->UserDataPos = ByteOffset;
|
||||
|
||||
// Set the position of the MPQ header
|
||||
ha->pHeader = (TMPQHeader *)ha->HeaderData;
|
||||
ha->MpqPos = ByteOffset;
|
||||
ha->FileSize = FileSize;
|
||||
|
||||
// Sector size must be nonzero.
|
||||
if(ByteOffset >= FileSize || ha->pHeader->wSectorSize == 0)
|
||||
dwErrCode = ERROR_BAD_FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix table positions according to format
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Dump the header
|
||||
// DumpMpqHeader(ha->pHeader);
|
||||
|
||||
// W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data,
|
||||
// and ignores the MPQ format version as well. The trick is to
|
||||
// fake MPQ format 2, with an improper hi-word position of hash table and block table
|
||||
// We can overcome such protectors by forcing opening the archive as MPQ v 1.0
|
||||
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
|
||||
{
|
||||
ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
|
||||
ha->pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
ha->pUserData = NULL;
|
||||
}
|
||||
|
||||
// Anti-overflow. If the hash table size in the header is
|
||||
// higher than 0x10000000, it would overflow in 32-bit version
|
||||
// Observed in the malformed Warcraft III maps
|
||||
// Example map: MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x
|
||||
ha->pHeader->dwBlockTableSize = (ha->pHeader->dwBlockTableSize & BLOCK_INDEX_MASK);
|
||||
ha->pHeader->dwHashTableSize = (ha->pHeader->dwHashTableSize & BLOCK_INDEX_MASK);
|
||||
|
||||
// Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
|
||||
if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
|
||||
// Check if the caller wants to force adding listfile
|
||||
if(dwFlags & MPQ_OPEN_FORCE_LISTFILE)
|
||||
ha->dwFlags |= MPQ_FLAG_LISTFILE_FORCE;
|
||||
|
||||
// StarDat.mpq from Starcraft I BETA: Enable special compression types
|
||||
if(IsStarcraftBetaArchive(ha->pHeader))
|
||||
ha->dwFlags |= MPQ_FLAG_STARCRAFT_BETA;
|
||||
|
||||
// Set the mask for the file offset. In MPQs version 1,
|
||||
// all offsets are 32-bit and overflow is allowed.
|
||||
// For MPQs v2+, file offset if 64-bit.
|
||||
ha->FileOffsetMask = GetFileOffsetMask(ha);
|
||||
|
||||
// Maps from StarCraft and Warcraft III need special treatment
|
||||
switch(MapType)
|
||||
{
|
||||
case MapTypeStarcraft:
|
||||
ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX;
|
||||
ha->dwFlags |= MPQ_FLAG_STARCRAFT;
|
||||
break;
|
||||
|
||||
case MapTypeWarcraft3:
|
||||
ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X;
|
||||
ha->dwFlags |= MPQ_FLAG_WAR3_MAP;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the size of file sector
|
||||
ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);
|
||||
|
||||
// Verify if any of the tables doesn't start beyond the end of the file
|
||||
dwErrCode = VerifyMpqTablePositions(ha, FileSize);
|
||||
}
|
||||
|
||||
// Read the hash table. Ignore the result, as hash table is no longer required
|
||||
// Read HET table. Ignore the result, as HET table is no longer required
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = LoadAnyHashTable(ha);
|
||||
}
|
||||
|
||||
// Now, build the file table. It will be built by combining
|
||||
// the block table, BET table, hi-block table, (attributes) and (listfile).
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = BuildFileTable(ha);
|
||||
}
|
||||
|
||||
// Load the internal listfile and include it to the file table
|
||||
if(dwErrCode == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
|
||||
{
|
||||
// Quick check for (listfile)
|
||||
pFileEntry = GetFileEntryLocale(ha, LISTFILE_NAME, LANG_NEUTRAL);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// Ignore result of the operation. (listfile) is optional.
|
||||
SFileAddListFile((HANDLE)ha, NULL);
|
||||
ha->dwFileFlags1 = pFileEntry->dwFlags;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the "(attributes)" file and merge it to the file table
|
||||
if(dwErrCode == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0 && (ha->dwFlags & MPQ_FLAG_BLOCK_TABLE_CUT) == 0)
|
||||
{
|
||||
// Quick check for (attributes)
|
||||
pFileEntry = GetFileEntryLocale(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// Ignore result of the operation. (attributes) is optional.
|
||||
SAttrLoadAttributes(ha);
|
||||
ha->dwFileFlags2 = pFileEntry->dwFlags;
|
||||
}
|
||||
}
|
||||
|
||||
// Remember whether the archive has weak signature. Only for MPQs format 1.0.
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Quick check for (signature)
|
||||
pFileEntry = GetFileEntryLocale(ha, SIGNATURE_NAME, LANG_NEUTRAL);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// Just remember that the archive is weak-signed
|
||||
assert((pFileEntry->dwFlags & MPQ_FILE_EXISTS) != 0);
|
||||
ha->dwFileFlags3 = pFileEntry->dwFlags;
|
||||
}
|
||||
|
||||
// Finally, set the MPQ_FLAG_READ_ONLY if the MPQ was found malformed
|
||||
ha->dwFlags |= (ha->dwFlags & MPQ_FLAG_MALFORMED) ? MPQ_FLAG_READ_ONLY : 0;
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
FreeArchiveHandle(ha);
|
||||
SetLastError(dwErrCode);
|
||||
ha = NULL;
|
||||
}
|
||||
|
||||
// Free the header buffer
|
||||
if(pbHeaderBuffer != NULL)
|
||||
STORM_FREE(pbHeaderBuffer);
|
||||
if(phMpq != NULL)
|
||||
*phMpq = ha;
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool WINAPI SFileSetDownloadCallback(HANDLE, SFILE_DOWNLOAD_CALLBACK, void *);
|
||||
//
|
||||
// Sets a callback that is called when content is downloaded from the master MPQ
|
||||
//
|
||||
|
||||
bool WINAPI SFileSetDownloadCallback(HANDLE hMpq, SFILE_DOWNLOAD_CALLBACK DownloadCB, void * pvUserData)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Do nothing if 'hMpq' is bad parameter
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return FileStream_SetCallback(ha->pStream, DownloadCB, pvUserData);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool SFileFlushArchive(HANDLE hMpq)
|
||||
//
|
||||
// Saves all dirty data into MPQ archive.
|
||||
// Has similar effect like SFileCloseArchive, but the archive is not closed.
|
||||
// Use on clients who keep MPQ archive open even for write operations,
|
||||
// and terminating without calling SFileCloseArchive might corrupt the archive.
|
||||
//
|
||||
|
||||
bool WINAPI SFileFlushArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha;
|
||||
DWORD dwResultError = ERROR_SUCCESS;
|
||||
DWORD dwErrCode;
|
||||
|
||||
// Do nothing if 'hMpq' is bad parameter
|
||||
if((ha = IsValidMpqHandle(hMpq)) == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only if the MPQ was changed
|
||||
if(ha->dwFlags & MPQ_FLAG_CHANGED)
|
||||
{
|
||||
// Indicate that we are saving MPQ internal structures
|
||||
ha->dwFlags |= MPQ_FLAG_SAVING_TABLES;
|
||||
|
||||
// Defragment the file table. This will allow us to put the internal files to the end
|
||||
DefragmentFileTable(ha);
|
||||
|
||||
//
|
||||
// Create each internal file
|
||||
// Note that the (signature) file is usually before (listfile) in the file table
|
||||
//
|
||||
|
||||
if(ha->dwFlags & MPQ_FLAG_SIGNATURE_NEW)
|
||||
{
|
||||
dwErrCode = SSignFileCreate(ha);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
dwResultError = dwErrCode;
|
||||
}
|
||||
|
||||
if(ha->dwFlags & (MPQ_FLAG_LISTFILE_NEW | MPQ_FLAG_LISTFILE_FORCE))
|
||||
{
|
||||
dwErrCode = SListFileSaveToMpq(ha);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
dwResultError = dwErrCode;
|
||||
}
|
||||
|
||||
if(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_NEW)
|
||||
{
|
||||
dwErrCode = SAttrFileSaveToMpq(ha);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
dwResultError = dwErrCode;
|
||||
}
|
||||
|
||||
// Save HET table, BET table, hash table, block table, hi-block table
|
||||
if(ha->dwFlags & MPQ_FLAG_CHANGED)
|
||||
{
|
||||
// Rebuild the HET table
|
||||
if(ha->pHetTable != NULL)
|
||||
RebuildHetTable(ha);
|
||||
|
||||
// Save all MPQ tables first
|
||||
dwErrCode = SaveMPQTables(ha);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
dwResultError = dwErrCode;
|
||||
|
||||
// If the archive has weak signature, we need to finish it
|
||||
if(ha->dwFileFlags3 != 0)
|
||||
{
|
||||
dwErrCode = SSignFileFinish(ha);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
dwResultError = dwErrCode;
|
||||
}
|
||||
}
|
||||
|
||||
// We are no longer saving internal MPQ structures
|
||||
ha->dwFlags &= ~MPQ_FLAG_SAVING_TABLES;
|
||||
}
|
||||
|
||||
// Return the error
|
||||
if(dwResultError != ERROR_SUCCESS)
|
||||
SetLastError(dwResultError);
|
||||
return (dwResultError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool SFileCloseArchive(HANDLE hMpq);
|
||||
//
|
||||
|
||||
bool WINAPI SFileCloseArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = IsValidMpqHandle(hMpq);
|
||||
bool bResult = false;
|
||||
|
||||
// Only if the handle is valid
|
||||
if(ha == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Invalidate the add file callback so it won't be called
|
||||
// when saving (listfile) and (attributes)
|
||||
ha->pfnAddFileCB = NULL;
|
||||
ha->pvAddFileUserData = NULL;
|
||||
|
||||
// Flush all unsaved data to the storage
|
||||
bResult = SFileFlushArchive(hMpq);
|
||||
|
||||
// Free all memory used by MPQ archive
|
||||
FreeArchiveHandle(ha);
|
||||
return bResult;
|
||||
}
|
||||
423
vendor/stormlib-9/src/SFileOpenFileEx.cpp
vendored
Normal file
423
vendor/stormlib-9/src/SFileOpenFileEx.cpp
vendored
Normal file
@ -0,0 +1,423 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad Created */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
// Finds hash index of the entry that was open by pseudo-name
|
||||
static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex)
|
||||
{
|
||||
TMPQHash * pHashTableEnd;
|
||||
TMPQHash * pHash;
|
||||
DWORD dwHashIndex = HASH_ENTRY_FREE;
|
||||
DWORD dwCount = 0;
|
||||
|
||||
// Should only be called if the archive has hash table
|
||||
assert(ha->pHashTable != NULL);
|
||||
|
||||
// Multiple hash table entries can point to the file table entry.
|
||||
// We need to search all of them
|
||||
pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
|
||||
{
|
||||
if(MPQ_BLOCK_INDEX(pHash) == dwFileIndex)
|
||||
{
|
||||
// Example: MPQ_2023_v1_Lusin2Rpg1.28.w3x, file index 24483
|
||||
// ReplaceableTextures\CommandButtons\BTNHaboss79.blp
|
||||
// Hash Table Index #1 = 18
|
||||
// Hash Table Index #2 = 8446
|
||||
if(dwCount++ > 0)
|
||||
return HASH_ENTRY_FREE;
|
||||
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the found hash index, if there are no duplicities
|
||||
return dwHashIndex;
|
||||
}
|
||||
|
||||
static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
|
||||
{
|
||||
TMPQNamePrefix * pPrefix;
|
||||
|
||||
// Are there patches in the current MPQ?
|
||||
if(ha->dwFlags & MPQ_FLAG_PATCH)
|
||||
{
|
||||
// The patch prefix must be already known here
|
||||
assert(ha->pPatchPrefix != NULL);
|
||||
pPrefix = ha->pPatchPrefix;
|
||||
|
||||
// The patch name for "OldWorld\\XXX\\YYY" is "Base\\XXX\YYY"
|
||||
// We need to remove the "OldWorld\\" prefix
|
||||
if(!_strnicmp(szFileName, "OldWorld\\", 9))
|
||||
szFileName += 9;
|
||||
|
||||
// Create the file name from the known patch entry
|
||||
memcpy(szBuffer, pPrefix->szPatchPrefix, pPrefix->nLength);
|
||||
strcpy(szBuffer + pPrefix->nLength, szFileName);
|
||||
szFileName = szBuffer;
|
||||
}
|
||||
|
||||
return szFileName;
|
||||
}
|
||||
|
||||
static bool OpenLocalFile(const char * szFileName, HANDLE * PtrFile)
|
||||
{
|
||||
TFileStream * pStream;
|
||||
TMPQFile * hf = NULL;
|
||||
TCHAR szFileNameT[MAX_PATH];
|
||||
|
||||
// Convert the file name to UNICODE (if needed)
|
||||
StringCopy(szFileNameT, _countof(szFileNameT), szFileName);
|
||||
|
||||
// Open the file and create the TMPQFile structure
|
||||
pStream = FileStream_OpenFile(szFileNameT, STREAM_FLAG_READ_ONLY);
|
||||
if(pStream != NULL)
|
||||
{
|
||||
// Allocate and initialize file handle
|
||||
hf = CreateFileHandle(NULL, NULL);
|
||||
if(hf != NULL)
|
||||
{
|
||||
hf->pStream = pStream;
|
||||
*PtrFile = hf;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
*PtrFile = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile)
|
||||
{
|
||||
TMPQArchive * haBase = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hfPatch; // Pointer to patch file
|
||||
TMPQFile * hfBase = NULL; // Pointer to base open file
|
||||
TMPQFile * hf = NULL;
|
||||
HANDLE hPatchFile;
|
||||
char szNameBuffer[MAX_PATH];
|
||||
|
||||
// First of all, find the latest archive where the file is in base version
|
||||
// (i.e. where the original, unpatched version of the file exists)
|
||||
while(ha != NULL)
|
||||
{
|
||||
// If the file is there, then we remember the archive
|
||||
pFileEntry = GetFileEntryExact(ha, GetPatchFileName(ha, szFileName, szNameBuffer), 0, NULL);
|
||||
if(pFileEntry != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
|
||||
haBase = ha;
|
||||
|
||||
// Move to the patch archive
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
// If we couldn't find the base file in any of the patches, it doesn't exist
|
||||
if((ha = haBase) != NULL)
|
||||
{
|
||||
// Now open the base file
|
||||
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
|
||||
{
|
||||
// The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
|
||||
assert((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0);
|
||||
hf = hfBase;
|
||||
|
||||
// Now open all patches and attach them on top of the base file
|
||||
for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
|
||||
{
|
||||
// Prepare the file name with a correct prefix
|
||||
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
|
||||
{
|
||||
// Remember the new version
|
||||
hfPatch = (TMPQFile *)hPatchFile;
|
||||
|
||||
// We should not find patch file
|
||||
assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
|
||||
|
||||
// Attach the patch to the base file
|
||||
hf->hfPatch = hfPatch;
|
||||
hf = hfPatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Give the updated base MPQ
|
||||
if(PtrFile != NULL)
|
||||
*PtrFile = (HANDLE)hfBase;
|
||||
return (hfBase != NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileEnumLocales enums all locale versions within MPQ.
|
||||
// Functions fills all available language identifiers on a file into the buffer
|
||||
// pointed by PtrFileLocales. There must be enough entries to copy the localed,
|
||||
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
|
||||
|
||||
DWORD WINAPI SFileEnumLocales(
|
||||
HANDLE hMpq,
|
||||
const char * szFileName,
|
||||
LCID * PtrFileLocales,
|
||||
LPDWORD PtrMaxLocales,
|
||||
DWORD dwSearchScope)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQHash * pFirstHash;
|
||||
TMPQHash * pHash;
|
||||
DWORD dwFileIndex = 0;
|
||||
DWORD dwMaxLocales;
|
||||
DWORD dwLocales = 0;
|
||||
|
||||
// Test the parameters
|
||||
if(!IsValidMpqHandle(hMpq))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
if(ha->pHashTable == NULL)
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
if(PtrMaxLocales == NULL)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
if(IsPseudoFileName(szFileName, &dwFileIndex))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Keep compilers happy
|
||||
dwMaxLocales = PtrMaxLocales[0];
|
||||
STORMLIB_UNUSED(dwSearchScope);
|
||||
|
||||
// Parse all files with that name
|
||||
pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
|
||||
while(pHash != NULL)
|
||||
{
|
||||
// Put the locales to the buffer
|
||||
if(PtrFileLocales != NULL && dwLocales < dwMaxLocales)
|
||||
*PtrFileLocales++ = SFILE_MAKE_LCID(pHash->Locale, pHash->Platform);
|
||||
dwLocales++;
|
||||
|
||||
// Get the next locale
|
||||
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
}
|
||||
|
||||
// Give the caller the number of locales and return
|
||||
PtrMaxLocales[0] = dwLocales;
|
||||
return (dwLocales <= dwMaxLocales) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenFileEx
|
||||
//
|
||||
// hMpq - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to open
|
||||
// dwSearchScope - Where to search
|
||||
// PtrFile - Pointer to store opened file handle
|
||||
|
||||
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile)
|
||||
{
|
||||
TMPQArchive * ha = IsValidMpqHandle(hMpq);
|
||||
TFileEntry * pFileEntry = NULL;
|
||||
TMPQFile * hf = NULL;
|
||||
DWORD dwHashIndex = HASH_ENTRY_FREE;
|
||||
DWORD dwFileIndex = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
bool bOpenByIndex = false;
|
||||
|
||||
// Don't accept NULL pointer to file handle
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
dwErrCode = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// When opening a file from MPQ, the handle must be valid
|
||||
if(dwSearchScope != SFILE_OPEN_LOCAL_FILE && ha == NULL)
|
||||
dwErrCode = ERROR_INVALID_HANDLE;
|
||||
|
||||
// When not checking for existence, the pointer to file handle must be valid
|
||||
if(dwSearchScope != SFILE_OPEN_CHECK_EXISTS && PtrFile == NULL)
|
||||
dwErrCode = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Prepare the file opening
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
switch(dwSearchScope)
|
||||
{
|
||||
case SFILE_OPEN_FROM_MPQ:
|
||||
case SFILE_OPEN_BASE_FILE:
|
||||
case SFILE_OPEN_CHECK_EXISTS:
|
||||
|
||||
// If this MPQ has no patches, open the file from this MPQ directly
|
||||
if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE)
|
||||
{
|
||||
pFileEntry = GetFileEntryLocale(ha, szFileName, g_lcFileLocale, &dwHashIndex);
|
||||
}
|
||||
|
||||
// If this MPQ is a patched archive, open the file as patched
|
||||
else
|
||||
{
|
||||
return OpenPatchedFile(hMpq, szFileName, PtrFile);
|
||||
}
|
||||
break;
|
||||
|
||||
case SFILE_OPEN_ANY_LOCALE:
|
||||
|
||||
// This open option is reserved for opening MPQ internal listfile.
|
||||
// No argument validation. Tries to open file with neutral locale first,
|
||||
// then any other available.
|
||||
pFileEntry = GetFileEntryLocale(ha, szFileName, 0, &dwHashIndex);
|
||||
break;
|
||||
|
||||
case SFILE_OPEN_LOCAL_FILE:
|
||||
|
||||
// Open a local file
|
||||
return OpenLocalFile(szFileName, PtrFile);
|
||||
|
||||
default:
|
||||
|
||||
// Don't accept any other value
|
||||
dwErrCode = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the file really exists in the MPQ
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// If we didn't find the file, try to open it using pseudo file name ("File
|
||||
if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
|
||||
{
|
||||
// Check the pseudo-file name ("File00000001.ext")
|
||||
if((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true)
|
||||
{
|
||||
// Get the file entry for the file
|
||||
if(dwFileIndex < ha->dwFileTableSize)
|
||||
{
|
||||
pFileEntry = ha->pFileTable + dwFileIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Still not found?
|
||||
if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
|
||||
{
|
||||
dwErrCode = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform some checks of invalid files
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// MPQ protectors use insanely amount of fake files, often with very high size.
|
||||
// We won't open any files whose compressed size is bigger than archive size
|
||||
// If the file is not compressed, its size cannot be bigger than archive size
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
|
||||
{
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
pFileEntry = NULL;
|
||||
}
|
||||
|
||||
// Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x)
|
||||
// if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
|
||||
// {
|
||||
// dwErrCode = ERROR_NOT_SUPPORTED;
|
||||
// pFileEntry = NULL;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Did the caller just wanted to know if the file exists?
|
||||
if(dwErrCode == ERROR_SUCCESS && dwSearchScope != SFILE_OPEN_CHECK_EXISTS)
|
||||
{
|
||||
// Allocate file handle
|
||||
hf = CreateFileHandle(ha, pFileEntry);
|
||||
if(hf != NULL)
|
||||
{
|
||||
// Get the hash index for the file
|
||||
if(ha->pHashTable != NULL && dwHashIndex == HASH_ENTRY_FREE)
|
||||
dwHashIndex = FindHashIndex(ha, dwFileIndex);
|
||||
if(dwHashIndex != HASH_ENTRY_FREE)
|
||||
hf->pHashEntry = ha->pHashTable + dwHashIndex;
|
||||
hf->dwHashIndex = dwHashIndex;
|
||||
|
||||
// If the MPQ has sector CRC enabled, enable if for the file
|
||||
if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
|
||||
hf->bCheckSectorCRCs = true;
|
||||
|
||||
// If we know the real file name, copy it to the file entry
|
||||
if(bOpenByIndex == false)
|
||||
{
|
||||
// If there is no file name yet, allocate it
|
||||
AllocateFileName(ha, pFileEntry, szFileName);
|
||||
|
||||
// If the file is encrypted, we should detect the file key
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
hf->dwFileKey = DecryptFileKey(szFileName,
|
||||
pFileEntry->ByteOffset,
|
||||
pFileEntry->dwFileSize,
|
||||
pFileEntry->dwFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Give the file entry
|
||||
if(PtrFile != NULL)
|
||||
PtrFile[0] = hf;
|
||||
|
||||
// Return error code
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileHasFile
|
||||
//
|
||||
// hMpq - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to look for
|
||||
|
||||
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
|
||||
{
|
||||
return SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_CHECK_EXISTS, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool WINAPI SFileCloseFile(HANDLE hFile);
|
||||
|
||||
bool WINAPI SFileCloseFile(HANDLE hFile)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(!IsValidFileHandle(hFile))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free the structure
|
||||
FreeFileHandle(hf);
|
||||
return true;
|
||||
}
|
||||
1175
vendor/stormlib-9/src/SFilePatchArchives.cpp
vendored
Normal file
1175
vendor/stormlib-9/src/SFilePatchArchives.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
910
vendor/stormlib-9/src/SFileReadFile.cpp
vendored
Normal file
910
vendor/stormlib-9/src/SFileReadFile.cpp
vendored
Normal file
@ -0,0 +1,910 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileReadFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad The first version of SFileReadFile.cpp */
|
||||
/* 24.03.99 1.00 Lad Added the SFileGetFileInfo function */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// External references (not public functions)
|
||||
|
||||
int WINAPI SCompDecompressX(TMPQArchive * ha, void * pvOutBuffer, int * pcbOutBuffer, void * pbInBuffer, int cbInBuffer);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
// hf - MPQ File handle.
|
||||
// pbBuffer - Pointer to target buffer to store sectors.
|
||||
// dwByteOffset - Position of sector in the file (relative to file begin)
|
||||
// dwBytesToRead - Number of bytes to read. Must be multiplier of sector size.
|
||||
// pdwBytesRead - Stored number of bytes loaded
|
||||
static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
ULONGLONG RawFilePos;
|
||||
TMPQArchive * ha = hf->ha;
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
LPBYTE pbRawSector = NULL;
|
||||
LPBYTE pbOutSector = pbBuffer;
|
||||
LPBYTE pbInSector = pbBuffer;
|
||||
DWORD dwRawBytesToRead;
|
||||
DWORD dwRawSectorOffset = dwByteOffset;
|
||||
DWORD dwSectorsToRead = dwBytesToRead / ha->dwSectorSize;
|
||||
DWORD dwSectorIndex = dwByteOffset / ha->dwSectorSize;
|
||||
DWORD dwSectorsDone = 0;
|
||||
DWORD dwBytesRead = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Note that dwByteOffset must be aligned to size of one sector
|
||||
// Note that dwBytesToRead must be a multiplier of one sector size
|
||||
// This is local function, so we won't check if that's true.
|
||||
// Note that files stored in single units are processed by a separate function
|
||||
|
||||
// If there is not enough bytes remaining, cut dwBytesToRead
|
||||
if((dwByteOffset + dwBytesToRead) > hf->dwDataSize)
|
||||
dwBytesToRead = hf->dwDataSize - dwByteOffset;
|
||||
dwRawBytesToRead = dwBytesToRead;
|
||||
|
||||
// Perform all necessary work to do with compressed files
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
{
|
||||
// If the sector positions are not loaded yet, do it
|
||||
if(hf->SectorOffsets == NULL)
|
||||
{
|
||||
dwErrCode = AllocateSectorOffsets(hf, true);
|
||||
if(dwErrCode != ERROR_SUCCESS || hf->SectorOffsets == NULL)
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
// If the sector checksums are not loaded yet, load them now.
|
||||
if(hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->bLoadedSectorCRCs == false)
|
||||
{
|
||||
//
|
||||
// Sector CRCs is plain crap feature. It is almost never present,
|
||||
// often it's empty, or the end offset of sector CRCs is zero.
|
||||
// We only try to load sector CRCs once, and regardless if it fails
|
||||
// or not, we won't try that again for the given file.
|
||||
//
|
||||
|
||||
AllocateSectorChecksums(hf, true);
|
||||
hf->bLoadedSectorCRCs = true;
|
||||
}
|
||||
|
||||
// TODO: If the raw data MD5s are not loaded yet, load them now
|
||||
// Only do it if the MPQ is of format 4.0
|
||||
// if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4 && ha->pHeader->dwRawChunkSize != 0)
|
||||
// {
|
||||
// dwErrCode = AllocateRawMD5s(hf, true);
|
||||
// if(dwErrCode != ERROR_SUCCESS)
|
||||
// return dwErrCode;
|
||||
// }
|
||||
|
||||
// Assign the temporary buffer as target for read operation
|
||||
dwRawSectorOffset = hf->SectorOffsets[dwSectorIndex];
|
||||
dwRawBytesToRead = hf->SectorOffsets[dwSectorIndex + dwSectorsToRead] - dwRawSectorOffset;
|
||||
|
||||
// If the file is compressed, also allocate secondary buffer
|
||||
pbInSector = pbRawSector = STORM_ALLOC(BYTE, dwRawBytesToRead);
|
||||
if(pbRawSector == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Calculate raw file offset where the sector(s) are stored.
|
||||
RawFilePos = CalculateRawSectorOffset(hf, dwRawSectorOffset);
|
||||
|
||||
// Set file pointer and read all required sectors
|
||||
if(FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead))
|
||||
{
|
||||
// Now we have to decrypt and decompress all file sectors that have been loaded
|
||||
for(DWORD i = 0; i < dwSectorsToRead; i++)
|
||||
{
|
||||
DWORD dwRawBytesInThisSector = ha->dwSectorSize;
|
||||
DWORD dwBytesInThisSector = ha->dwSectorSize;
|
||||
DWORD dwIndex = dwSectorIndex + i;
|
||||
|
||||
// If there is not enough bytes in the last sector,
|
||||
// cut the number of bytes in this sector
|
||||
if(dwRawBytesInThisSector > dwBytesToRead)
|
||||
dwRawBytesInThisSector = dwBytesToRead;
|
||||
if(dwBytesInThisSector > dwBytesToRead)
|
||||
dwBytesInThisSector = dwBytesToRead;
|
||||
|
||||
// If the file is compressed, we have to adjust the raw sector size
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex];
|
||||
|
||||
// If the file is encrypted, we have to decrypt the sector
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
|
||||
|
||||
// If we don't know the key, try to detect it by file content
|
||||
if(hf->dwFileKey == 0)
|
||||
{
|
||||
hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector, hf->dwDataSize);
|
||||
if(hf->dwFileKey == 0)
|
||||
{
|
||||
dwErrCode = ERROR_UNKNOWN_FILE_KEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex);
|
||||
BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
|
||||
}
|
||||
|
||||
// If the file has sector CRC check turned on, perform it
|
||||
if(hf->bCheckSectorCRCs && hf->SectorChksums != NULL)
|
||||
{
|
||||
DWORD dwAdlerExpected = hf->SectorChksums[dwIndex];
|
||||
DWORD dwAdlerValue = 0;
|
||||
|
||||
// We can only check sector CRC when it's not zero
|
||||
// Neither can we check it if it's 0xFFFFFFFF.
|
||||
if(dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF)
|
||||
{
|
||||
dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector);
|
||||
if(dwAdlerValue != dwAdlerExpected)
|
||||
{
|
||||
dwErrCode = ERROR_CHECKSUM_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the sector is really compressed, decompress it.
|
||||
// WARNING : Some sectors may not be compressed, it can be determined only
|
||||
// by comparing uncompressed and compressed size !!!
|
||||
if(dwRawBytesInThisSector < dwBytesInThisSector)
|
||||
{
|
||||
if(dwRawBytesInThisSector != 0)
|
||||
{
|
||||
int cbOutSector = dwBytesInThisSector;
|
||||
int cbInSector = dwRawBytesInThisSector;
|
||||
int nResult = 0;
|
||||
|
||||
// Is the file compressed by Blizzard's multiple compression ?
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
|
||||
{
|
||||
// Remember the last used compression
|
||||
hf->dwCompression0 = pbInSector[0];
|
||||
|
||||
// Decompress the data. We need to perform MPQ-specific decompression,
|
||||
// as multiple Blizzard games may have their own decompression tables
|
||||
// and even decompression methods.
|
||||
nResult = SCompDecompressX(ha, pbOutSector, &cbOutSector, pbInSector, cbInSector);
|
||||
}
|
||||
|
||||
// Is the file compressed by PKWARE Data Compression Library ?
|
||||
else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
|
||||
{
|
||||
nResult = SCompExplode(pbOutSector, &cbOutSector, pbInSector, cbInSector);
|
||||
}
|
||||
|
||||
// Did the decompression fail ?
|
||||
if(nResult == 0)
|
||||
{
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(pbOutSector, 0, dwBytesInThisSector);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pbOutSector != pbInSector)
|
||||
memcpy(pbOutSector, pbInSector, dwBytesInThisSector);
|
||||
}
|
||||
|
||||
// Move pointers
|
||||
dwBytesToRead -= dwBytesInThisSector;
|
||||
dwByteOffset += dwBytesInThisSector;
|
||||
dwBytesRead += dwBytesInThisSector;
|
||||
pbOutSector += dwBytesInThisSector;
|
||||
pbInSector += dwRawBytesInThisSector;
|
||||
dwSectorsDone++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
|
||||
// Free all used buffers
|
||||
if(pbRawSector != NULL)
|
||||
STORM_FREE(pbRawSector);
|
||||
|
||||
// Give the caller thenumber of bytes read
|
||||
*pdwBytesRead = dwBytesRead;
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
ULONGLONG RawFilePos = hf->RawFilePos;
|
||||
TMPQArchive * ha = hf->ha;
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
LPBYTE pbCompressed = NULL;
|
||||
LPBYTE pbRawData;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// If the file buffer is not allocated yet, do it.
|
||||
if(hf->pbFileSector == NULL)
|
||||
{
|
||||
dwErrCode = AllocateSectorBuffer(hf);
|
||||
if(dwErrCode != ERROR_SUCCESS || hf->pbFileSector == NULL)
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
// If the file is a patch file, adjust raw data offset
|
||||
if(hf->pPatchInfo != NULL)
|
||||
RawFilePos += hf->pPatchInfo->dwLength;
|
||||
pbRawData = hf->pbFileSector;
|
||||
|
||||
// If the file sector is not loaded yet, do it
|
||||
if(hf->dwSectorOffs != 0)
|
||||
{
|
||||
// Is the file compressed?
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
{
|
||||
// Allocate space for compressed data
|
||||
pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize);
|
||||
if(pbCompressed == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
pbRawData = pbCompressed;
|
||||
}
|
||||
|
||||
// Load the raw (compressed, encrypted) data
|
||||
if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize))
|
||||
{
|
||||
STORM_FREE(pbCompressed);
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
// If the file is encrypted, we have to decrypt the data first
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
|
||||
DecryptMpqBlock(pbRawData, pFileEntry->dwCmpSize, hf->dwFileKey);
|
||||
BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize);
|
||||
}
|
||||
|
||||
// If the file is compressed, we have to decompress it now
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
{
|
||||
int cbOutBuffer = (int)hf->dwDataSize;
|
||||
int cbInBuffer = (int)pFileEntry->dwCmpSize;
|
||||
int nResult = 0;
|
||||
|
||||
//
|
||||
// If the file is an incremental patch, the size of compressed data
|
||||
// is determined as pFileEntry->dwCmpSize - sizeof(TPatchInfo)
|
||||
//
|
||||
// In "wow-update-12694.MPQ" from Wow-Cataclysm BETA:
|
||||
//
|
||||
// File CmprSize DcmpSize DataSize Compressed?
|
||||
// -------------------------------------- ---------- -------- -------- ---------------
|
||||
// esES\DBFilesClient\LightSkyBox.dbc 0xBE->0xA2 0xBC 0xBC Yes
|
||||
// deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No
|
||||
//
|
||||
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
cbInBuffer = cbInBuffer - sizeof(TPatchInfo);
|
||||
|
||||
// Is the file compressed by Blizzard's multiple compression ?
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
|
||||
{
|
||||
// Remember the last used compression
|
||||
hf->dwCompression0 = pbRawData[0];
|
||||
|
||||
// Decompress the file
|
||||
if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
|
||||
nResult = SCompDecompress2(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
|
||||
else
|
||||
nResult = SCompDecompress(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
|
||||
}
|
||||
|
||||
// Is the file compressed by PKWARE Data Compression Library ?
|
||||
// Note: Single unit files compressed with IMPLODE are not supported by Blizzard
|
||||
else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
|
||||
nResult = SCompExplode(hf->pbFileSector, &cbOutBuffer, pbRawData, cbInBuffer);
|
||||
|
||||
dwErrCode = (nResult != 0) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hf->pbFileSector != NULL && pbRawData != hf->pbFileSector)
|
||||
memcpy(hf->pbFileSector, pbRawData, hf->dwDataSize);
|
||||
}
|
||||
|
||||
// Free the decompression buffer.
|
||||
if(pbCompressed != NULL)
|
||||
STORM_FREE(pbCompressed);
|
||||
|
||||
// The file sector is now properly loaded
|
||||
hf->dwSectorOffs = 0;
|
||||
}
|
||||
|
||||
// At this moment, we have the file loaded into the file buffer.
|
||||
// Copy as much as the caller wants
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->dwSectorOffs == 0)
|
||||
{
|
||||
// File position is greater or equal to file size ?
|
||||
if(dwFilePos >= hf->dwDataSize)
|
||||
{
|
||||
*pdwBytesRead = 0;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// If not enough bytes remaining in the file, cut them
|
||||
if((hf->dwDataSize - dwFilePos) < dwToRead)
|
||||
dwToRead = (hf->dwDataSize - dwFilePos);
|
||||
|
||||
// Copy the bytes
|
||||
memcpy(pvBuffer, hf->pbFileSector + dwFilePos, dwToRead);
|
||||
|
||||
// Give the number of bytes read
|
||||
*pdwBytesRead = dwToRead;
|
||||
}
|
||||
|
||||
// An error, sorry
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD ReadMpkFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
ULONGLONG RawFilePos = hf->RawFilePos + 0x0C; // For some reason, MPK files start at position (hf->RawFilePos + 0x0C)
|
||||
TMPQArchive * ha = hf->ha;
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
LPBYTE pbCompressed = NULL;
|
||||
LPBYTE pbRawData = hf->pbFileSector;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// We do not support patch files in MPK archives
|
||||
assert(hf->pPatchInfo == NULL);
|
||||
|
||||
// If the file buffer is not allocated yet, do it.
|
||||
if(hf->pbFileSector == NULL)
|
||||
{
|
||||
dwErrCode = AllocateSectorBuffer(hf);
|
||||
if(dwErrCode != ERROR_SUCCESS || hf->pbFileSector == NULL)
|
||||
return dwErrCode;
|
||||
pbRawData = hf->pbFileSector;
|
||||
}
|
||||
|
||||
// If the file sector is not loaded yet, do it
|
||||
if(hf->dwSectorOffs != 0)
|
||||
{
|
||||
// Is the file compressed?
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
{
|
||||
// Allocate space for compressed data
|
||||
pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize);
|
||||
if(pbCompressed == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
pbRawData = pbCompressed;
|
||||
}
|
||||
|
||||
// Load the raw (compressed, encrypted) data
|
||||
if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize))
|
||||
{
|
||||
STORM_FREE(pbCompressed);
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
// If the file is encrypted, we have to decrypt the data first
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
DecryptMpkTable(pbRawData, pFileEntry->dwCmpSize);
|
||||
}
|
||||
|
||||
// If the file is compressed, we have to decompress it now on
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
|
||||
{
|
||||
int cbOutBuffer = (int)hf->dwDataSize;
|
||||
|
||||
hf->dwCompression0 = pbRawData[0];
|
||||
if(!SCompDecompressMpk(hf->pbFileSector, &cbOutBuffer, pbRawData, (int)pFileEntry->dwCmpSize))
|
||||
dwErrCode = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pbRawData != hf->pbFileSector)
|
||||
memcpy(hf->pbFileSector, pbRawData, hf->dwDataSize);
|
||||
}
|
||||
|
||||
// Free the decompression buffer.
|
||||
if(pbCompressed != NULL)
|
||||
STORM_FREE(pbCompressed);
|
||||
|
||||
// The file sector is now properly loaded
|
||||
hf->dwSectorOffs = 0;
|
||||
}
|
||||
|
||||
// At this moment, we have the file loaded into the file buffer.
|
||||
// Copy as much as the caller wants
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->dwSectorOffs == 0)
|
||||
{
|
||||
// File position is greater or equal to file size ?
|
||||
if(dwFilePos >= hf->dwDataSize)
|
||||
{
|
||||
*pdwBytesRead = 0;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// If not enough bytes remaining in the file, cut them
|
||||
if((hf->dwDataSize - dwFilePos) < dwToRead)
|
||||
dwToRead = (hf->dwDataSize - dwFilePos);
|
||||
|
||||
// Copy the bytes
|
||||
memcpy(pvBuffer, hf->pbFileSector + dwFilePos, dwToRead);
|
||||
|
||||
// Give the number of bytes read
|
||||
*pdwBytesRead = dwToRead;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// An error, sorry
|
||||
return ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
static DWORD ReadMpqFileSectorFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwBytesToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
TMPQArchive * ha = hf->ha;
|
||||
LPBYTE pbBuffer = (BYTE *)pvBuffer;
|
||||
DWORD dwTotalBytesRead = 0; // Total bytes read in all three parts
|
||||
DWORD dwSectorSizeMask = ha->dwSectorSize - 1; // Mask for block size, usually 0x0FFF
|
||||
DWORD dwFileSectorPos; // File offset of the loaded sector
|
||||
DWORD dwBytesRead; // Number of bytes read (temporary variable)
|
||||
DWORD dwErrCode;
|
||||
|
||||
// If the file position is at or beyond end of file, do nothing
|
||||
if(dwFilePos >= hf->dwDataSize)
|
||||
{
|
||||
*pdwBytesRead = 0;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// If not enough bytes in the file remaining, cut them
|
||||
if(dwBytesToRead > (hf->dwDataSize - dwFilePos))
|
||||
dwBytesToRead = (hf->dwDataSize - dwFilePos);
|
||||
|
||||
// Compute sector position in the file
|
||||
dwFileSectorPos = dwFilePos & ~dwSectorSizeMask; // Position in the block
|
||||
|
||||
// If the file sector buffer is not allocated yet, do it now
|
||||
if(hf->pbFileSector == NULL)
|
||||
{
|
||||
dwErrCode = AllocateSectorBuffer(hf);
|
||||
if(dwErrCode != ERROR_SUCCESS || hf->pbFileSector == NULL)
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
// Load the first (incomplete) file sector
|
||||
if(dwFilePos & dwSectorSizeMask)
|
||||
{
|
||||
DWORD dwBytesInSector = ha->dwSectorSize;
|
||||
DWORD dwBufferOffs = dwFilePos & dwSectorSizeMask;
|
||||
DWORD dwToCopy;
|
||||
|
||||
// Is the file sector already loaded ?
|
||||
if(hf->dwSectorOffs != dwFileSectorPos)
|
||||
{
|
||||
// Load one MPQ sector into archive buffer
|
||||
dwErrCode = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesInSector);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// Remember that the data loaded to the sector have new file offset
|
||||
hf->dwSectorOffs = dwFileSectorPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((dwFileSectorPos + dwBytesInSector) > hf->dwDataSize)
|
||||
dwBytesInSector = hf->dwDataSize - dwFileSectorPos;
|
||||
}
|
||||
|
||||
// Copy the data from the offset in the loaded sector to the end of the sector
|
||||
dwToCopy = dwBytesInSector - dwBufferOffs;
|
||||
if(dwToCopy > dwBytesToRead)
|
||||
dwToCopy = dwBytesToRead;
|
||||
|
||||
// Copy data from sector buffer into target buffer
|
||||
memcpy(pbBuffer, hf->pbFileSector + dwBufferOffs, dwToCopy);
|
||||
|
||||
// Update pointers and byte counts
|
||||
dwTotalBytesRead += dwToCopy;
|
||||
dwFileSectorPos += dwBytesInSector;
|
||||
pbBuffer += dwToCopy;
|
||||
dwBytesToRead -= dwToCopy;
|
||||
}
|
||||
|
||||
// Load the whole ("middle") sectors only if there is at least one full sector to be read
|
||||
if(dwBytesToRead >= ha->dwSectorSize)
|
||||
{
|
||||
DWORD dwBlockBytes = dwBytesToRead & ~dwSectorSizeMask;
|
||||
|
||||
// Load all sectors to the output buffer
|
||||
dwErrCode = ReadMpqSectors(hf, pbBuffer, dwFileSectorPos, dwBlockBytes, &dwBytesRead);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// Update pointers
|
||||
dwTotalBytesRead += dwBytesRead;
|
||||
dwFileSectorPos += dwBytesRead;
|
||||
pbBuffer += dwBytesRead;
|
||||
dwBytesToRead -= dwBytesRead;
|
||||
}
|
||||
|
||||
// Read the terminating sector
|
||||
if(dwBytesToRead > 0)
|
||||
{
|
||||
DWORD dwToCopy = ha->dwSectorSize;
|
||||
|
||||
// Is the file sector already loaded ?
|
||||
if(hf->dwSectorOffs != dwFileSectorPos)
|
||||
{
|
||||
// Load one MPQ sector into archive buffer
|
||||
dwErrCode = ReadMpqSectors(hf, hf->pbFileSector, dwFileSectorPos, ha->dwSectorSize, &dwBytesRead);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// Remember that the data loaded to the sector have new file offset
|
||||
hf->dwSectorOffs = dwFileSectorPos;
|
||||
}
|
||||
|
||||
// Check number of bytes read
|
||||
if(dwToCopy > dwBytesToRead)
|
||||
dwToCopy = dwBytesToRead;
|
||||
|
||||
// Copy the data from the cached last sector to the caller's buffer
|
||||
memcpy(pbBuffer, hf->pbFileSector, dwToCopy);
|
||||
|
||||
// Update pointers
|
||||
dwTotalBytesRead += dwToCopy;
|
||||
}
|
||||
|
||||
// Store total number of bytes read to the caller
|
||||
*pdwBytesRead = dwTotalBytesRead;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD ReadMpqFilePatchFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
TMPQPatcher Patcher;
|
||||
DWORD dwBytesToRead = dwToRead;
|
||||
DWORD dwBytesRead = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Make sure that the patch file is loaded completely
|
||||
if(dwErrCode == ERROR_SUCCESS && hf->pbFileData == NULL)
|
||||
{
|
||||
// Initialize patching process and allocate data
|
||||
dwErrCode = Patch_InitPatcher(&Patcher, hf);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// Set the current data size
|
||||
Patcher.cbFileData = hf->pFileEntry->dwFileSize;
|
||||
|
||||
// Initialize the patcher object with initial file data
|
||||
if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
|
||||
dwErrCode = ReadMpqFileSingleUnit(hf, Patcher.pbFileData1, 0, Patcher.cbFileData, &dwBytesRead);
|
||||
else
|
||||
dwErrCode = ReadMpqFileSectorFile(hf, Patcher.pbFileData1, 0, Patcher.cbFileData, &dwBytesRead);
|
||||
|
||||
// Perform the patching process
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
dwErrCode = Patch_Process(&Patcher, hf);
|
||||
|
||||
// Finalize the patcher structure
|
||||
Patch_Finalize(&Patcher);
|
||||
dwBytesRead = 0;
|
||||
}
|
||||
|
||||
// If there is something to read, do it
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
if(dwFilePos < hf->cbFileData)
|
||||
{
|
||||
// Make sure we don't copy more than file size
|
||||
if((dwFilePos + dwToRead) > hf->cbFileData)
|
||||
dwToRead = hf->cbFileData - dwFilePos;
|
||||
|
||||
// Copy the appropriate amount of the file data to the caller's buffer
|
||||
memcpy(pvBuffer, hf->pbFileData + dwFilePos, dwToRead);
|
||||
dwBytesRead = dwToRead;
|
||||
}
|
||||
|
||||
// Set the proper error code
|
||||
dwErrCode = (dwBytesRead == dwBytesToRead) ? ERROR_SUCCESS : ERROR_HANDLE_EOF;
|
||||
}
|
||||
|
||||
// Give the result to the caller
|
||||
if(pdwBytesRead != NULL)
|
||||
*pdwBytesRead = dwBytesRead;
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
static DWORD ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos, DWORD dwToRead, LPDWORD pdwBytesRead)
|
||||
{
|
||||
ULONGLONG FilePosition1 = dwFilePos;
|
||||
ULONGLONG FilePosition2;
|
||||
DWORD dwBytesRead = 0;
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
assert(hf->pStream != NULL);
|
||||
|
||||
// Because stream I/O functions are designed to read
|
||||
// "all or nothing", we compare file position before and after,
|
||||
// and if they differ, we assume that number of bytes read
|
||||
// is the difference between them
|
||||
|
||||
if(!FileStream_Read(hf->pStream, &FilePosition1, pvBuffer, dwToRead))
|
||||
{
|
||||
// If not all bytes have been read, then return the number of bytes read
|
||||
if((dwErrCode = GetLastError()) == ERROR_HANDLE_EOF)
|
||||
{
|
||||
FileStream_GetPos(hf->pStream, &FilePosition2);
|
||||
dwBytesRead = (DWORD)(FilePosition2 - FilePosition1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwBytesRead = dwToRead;
|
||||
}
|
||||
|
||||
*pdwBytesRead = dwBytesRead;
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileReadFile
|
||||
|
||||
bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf;
|
||||
DWORD dwBytesRead = 0; // Number of bytes read
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Always zero the result
|
||||
if(pdwRead != NULL)
|
||||
*pdwRead = 0;
|
||||
lpOverlapped = lpOverlapped;
|
||||
|
||||
// Check valid parameters
|
||||
if((hf = IsValidFileHandle(hFile)) == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(pvBuffer == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we didn't load the patch info yet, do it now
|
||||
if(hf->pFileEntry != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) && hf->pPatchInfo == NULL)
|
||||
{
|
||||
dwErrCode = AllocatePatchInfo(hf, true);
|
||||
if(dwErrCode != ERROR_SUCCESS || hf->pPatchInfo == NULL)
|
||||
{
|
||||
SetLastError(dwErrCode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the last used compression
|
||||
pFileEntry = hf->pFileEntry;
|
||||
hf->dwCompression0 = 0;
|
||||
|
||||
// If the file is local file, read the data directly from the stream
|
||||
if(hf->pStream != NULL)
|
||||
{
|
||||
dwErrCode = ReadMpqFileLocalFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
|
||||
}
|
||||
|
||||
// If the file is a patch file, we have to read it special way
|
||||
else if(hf->hfPatch != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
|
||||
{
|
||||
dwErrCode = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
|
||||
}
|
||||
|
||||
// If the archive is a MPK archive, we need special way to read the file
|
||||
else if(hf->ha->dwSubType == MPQ_SUBTYPE_MPK)
|
||||
{
|
||||
dwErrCode = ReadMpkFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
|
||||
}
|
||||
|
||||
// If the file is single unit file, redirect it to read file
|
||||
else if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
|
||||
{
|
||||
dwErrCode = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
|
||||
}
|
||||
|
||||
// Otherwise read it as sector based MPQ file
|
||||
else
|
||||
{
|
||||
dwErrCode = ReadMpqFileSectorFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
|
||||
}
|
||||
|
||||
// Increment the file position
|
||||
hf->dwFilePos += dwBytesRead;
|
||||
|
||||
// Give the caller the number of bytes read
|
||||
if(pdwRead != NULL)
|
||||
*pdwRead = dwBytesRead;
|
||||
|
||||
// If the read operation succeeded, but not full number of bytes was read,
|
||||
// set the last error to ERROR_HANDLE_EOF
|
||||
if(dwErrCode == ERROR_SUCCESS && (dwBytesRead < dwToRead))
|
||||
dwErrCode = ERROR_HANDLE_EOF;
|
||||
|
||||
// If something failed, set the last error value
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
SetLastError(dwErrCode);
|
||||
return (dwErrCode == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetFileSize
|
||||
|
||||
DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
|
||||
{
|
||||
ULONGLONG FileSize;
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
// Validate the file handle before we go on
|
||||
if(IsValidFileHandle(hFile))
|
||||
{
|
||||
// Make sure that the variable is initialized
|
||||
FileSize = 0;
|
||||
|
||||
// If the file is patched file, we have to get the size of the last version
|
||||
if(hf->hfPatch != NULL)
|
||||
{
|
||||
// Walk through the entire patch chain, take the last version
|
||||
while(hf != NULL)
|
||||
{
|
||||
// Get the size of the currently pointed version
|
||||
FileSize = hf->pFileEntry->dwFileSize;
|
||||
|
||||
// Move to the next patch file in the hierarchy
|
||||
hf = hf->hfPatch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is it a local file ?
|
||||
if(hf->pStream != NULL)
|
||||
{
|
||||
FileStream_GetSize(hf->pStream, &FileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSize = hf->dwDataSize;
|
||||
}
|
||||
}
|
||||
|
||||
// If opened from archive, return file size
|
||||
if(pdwFileSizeHigh != NULL)
|
||||
*pdwFileSizeHigh = (DWORD)(FileSize >> 32);
|
||||
return (DWORD)FileSize;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return SFILE_INVALID_SIZE;
|
||||
}
|
||||
|
||||
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
ULONGLONG OldPosition;
|
||||
ULONGLONG NewPosition;
|
||||
ULONGLONG FileSize;
|
||||
ULONGLONG DeltaPos;
|
||||
|
||||
// If the hFile is not a valid file handle, return an error.
|
||||
if(!IsValidFileHandle(hFile))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return SFILE_INVALID_POS;
|
||||
}
|
||||
|
||||
// Retrieve the file size for handling the limits
|
||||
if(hf->pStream != NULL)
|
||||
{
|
||||
FileStream_GetSize(hf->pStream, &FileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSize = SFileGetFileSize(hFile, NULL);
|
||||
}
|
||||
|
||||
// Handle the NULL and non-NULL values of plFilePosHigh
|
||||
// Non-NULL: The DeltaPos is combined from lFilePos and *lpFilePosHigh
|
||||
// NULL: The DeltaPos is sign-extended value of lFilePos
|
||||
DeltaPos = (plFilePosHigh != NULL) ? MAKE_OFFSET64(plFilePosHigh[0], lFilePos) : (ULONGLONG)(LONGLONG)lFilePos;
|
||||
|
||||
// Get the relative point where to move from
|
||||
switch(dwMoveMethod)
|
||||
{
|
||||
case FILE_BEGIN:
|
||||
|
||||
// Move relative to the file begin.
|
||||
OldPosition = 0;
|
||||
break;
|
||||
|
||||
case FILE_CURRENT:
|
||||
|
||||
// Retrieve the current file position
|
||||
if(hf->pStream != NULL)
|
||||
{
|
||||
FileStream_GetPos(hf->pStream, &OldPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
OldPosition = hf->dwFilePos;
|
||||
}
|
||||
break;
|
||||
|
||||
case FILE_END:
|
||||
|
||||
// Move relative to the end of the file
|
||||
OldPosition = FileSize;
|
||||
break;
|
||||
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return SFILE_INVALID_POS;
|
||||
}
|
||||
|
||||
// Calculate the new position
|
||||
NewPosition = OldPosition + DeltaPos;
|
||||
|
||||
// If moving backward, don't allow the new position go negative
|
||||
if((LONGLONG)DeltaPos < 0)
|
||||
{
|
||||
if(NewPosition > FileSize) // Position is negative
|
||||
{
|
||||
SetLastError(ERROR_NEGATIVE_SEEK);
|
||||
return SFILE_INVALID_POS;
|
||||
}
|
||||
}
|
||||
|
||||
// If moving forward, don't allow the new position go past the end of the file
|
||||
else
|
||||
{
|
||||
if(NewPosition > FileSize)
|
||||
NewPosition = FileSize;
|
||||
}
|
||||
|
||||
// Now apply the file pointer to the file
|
||||
if(hf->pStream != NULL)
|
||||
{
|
||||
if(!FileStream_Read(hf->pStream, &NewPosition, NULL, 0))
|
||||
return SFILE_INVALID_POS;
|
||||
}
|
||||
|
||||
// Also, store the new file position to the TMPQFile struct
|
||||
hf->dwFilePos = (DWORD)NewPosition;
|
||||
|
||||
// Return the new file position
|
||||
if(plFilePosHigh != NULL)
|
||||
*plFilePosHigh = (LONG)(NewPosition >> 32);
|
||||
return (DWORD)NewPosition;
|
||||
}
|
||||
1059
vendor/stormlib-9/src/SFileVerify.cpp
vendored
Normal file
1059
vendor/stormlib-9/src/SFileVerify.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
449
vendor/stormlib-9/src/StormCommon.h
vendored
Normal file
449
vendor/stormlib-9/src/StormCommon.h
vendored
Normal file
@ -0,0 +1,449 @@
|
||||
/*****************************************************************************/
|
||||
/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Common functions for encryption/decryption from Storm.dll. Included by */
|
||||
/* SFile*** functions, do not include and do not use this file directly */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
|
||||
/* 12.06.04 1.00 Lad Renamed to SCommon.h */
|
||||
/* 06.09.10 1.00 Lad Renamed to StormCommon.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMCOMMON_H__
|
||||
#define __STORMCOMMON_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compression support
|
||||
|
||||
// Include functions from Pkware Data Compression Library
|
||||
#include "pklib/pklib.h"
|
||||
|
||||
// Include functions from Huffmann compression
|
||||
#include "huffman/huff.h"
|
||||
|
||||
// Include functions from IMA ADPCM compression
|
||||
#include "adpcm/adpcm.h"
|
||||
|
||||
// Include functions from SPARSE compression
|
||||
#include "sparse/sparse.h"
|
||||
|
||||
// Include functions from LZMA compression
|
||||
#include "lzma/C/LzmaEnc.h"
|
||||
#include "lzma/C/LzmaDec.h"
|
||||
|
||||
// Include functions from zlib
|
||||
#ifndef __SYS_ZLIB
|
||||
#include "zlib/zlib.h"
|
||||
#else
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
// Include functions from bzlib
|
||||
#ifndef __SYS_BZLIB
|
||||
#include "bzip2/bzlib.h"
|
||||
#else
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cryptography support
|
||||
|
||||
// Headers from LibTomCrypt
|
||||
#include "libtomcrypt/src/headers/tomcrypt.h"
|
||||
|
||||
// For HashStringJenkins
|
||||
#include "jenkins/lookup.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StormLib private defines
|
||||
|
||||
#define ID_MPQ_FILE 0x46494c45 // Used internally for checking TMPQFile ('FILE')
|
||||
|
||||
// Prevent problems with CRT "min" and "max" functions,
|
||||
// as they are not defined on all platforms
|
||||
#define STORMLIB_MIN(a, b) ((a < b) ? a : b)
|
||||
#define STORMLIB_MAX(a, b) ((a > b) ? a : b)
|
||||
#define STORMLIB_UNUSED(p) ((void)(p))
|
||||
|
||||
// Checks for data pointers aligned to 4-byte boundary
|
||||
#define STORMLIB_DWORD_ALIGNED(ptr) (((size_t)(ptr) & 0x03) == 0)
|
||||
|
||||
// Check for masked flags
|
||||
#define STORMLIB_TEST_FLAGS(dwFlags, dwMask, dwValue) ((dwFlags & (dwMask)) == (dwValue))
|
||||
|
||||
// Macro for building 64-bit file offset from two 32-bit
|
||||
#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | (ULONGLONG)lo)
|
||||
|
||||
// Macro for checking a valid, non-empty ASCIIZ string
|
||||
#ifndef IS_VALID_STRING
|
||||
#define IS_VALID_STRING(str) (str && str[0])
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MTYPE definition - specifies what kind of MPQ is the file
|
||||
|
||||
typedef enum _MTYPE
|
||||
{
|
||||
MapTypeNotChecked, // The map type was not checked yet
|
||||
MapTypeNotRecognized, // The file does not seems to be a map
|
||||
MapTypeAviFile, // The file is actually an AVI file (Warcraft III cinematics)
|
||||
MapTypeStarcraft, // The file is a Starcraft map
|
||||
MapTypeWarcraft3, // The file is a Warcraft III map
|
||||
MapTypeStarcraft2 // The file is a Starcraft II map
|
||||
} MTYPE, *PMTYPE;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MPQ signature information
|
||||
|
||||
// Size of each signature type
|
||||
#define MPQ_WEAK_SIGNATURE_SIZE 64
|
||||
#define MPQ_STRONG_SIGNATURE_SIZE 256
|
||||
#define MPQ_STRONG_SIGNATURE_ID 0x5349474E // ID of the strong signature ("NGIS")
|
||||
#define MPQ_SIGNATURE_FILE_SIZE (MPQ_WEAK_SIGNATURE_SIZE + 8)
|
||||
|
||||
// MPQ signature info
|
||||
typedef struct _MPQ_SIGNATURE_INFO
|
||||
{
|
||||
ULONGLONG BeginMpqData; // File offset where the hashing starts
|
||||
ULONGLONG BeginExclude; // Begin of the excluded area (used for (signature) file)
|
||||
ULONGLONG EndExclude; // End of the excluded area (used for (signature) file)
|
||||
ULONGLONG EndMpqData; // File offset where the hashing ends
|
||||
ULONGLONG EndOfFile; // Size of the entire file
|
||||
BYTE Signature[MPQ_STRONG_SIGNATURE_SIZE + 0x10];
|
||||
DWORD cbSignatureSize; // Length of the signature
|
||||
DWORD SignatureTypes; // See SIGNATURE_TYPE_XXX
|
||||
|
||||
} MPQ_SIGNATURE_INFO, *PMPQ_SIGNATURE_INFO;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory management
|
||||
//
|
||||
// We use our own macros for allocating/freeing memory. If you want
|
||||
// to redefine them, please keep the following rules:
|
||||
//
|
||||
// - The memory allocation must return NULL if not enough memory
|
||||
// (i.e not to throw exception)
|
||||
// - The allocating function does not need to fill the allocated buffer with zeros
|
||||
// - Memory freeing function doesn't have to test the pointer to NULL
|
||||
//
|
||||
|
||||
//#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
//
|
||||
//#define STORM_ALLOC(type, nitems) (type *)HeapAlloc(GetProcessHeap(), 0, ((nitems) * sizeof(type)))
|
||||
//#define STORM_REALLOC(type, ptr, nitems) (type *)HeapReAlloc(GetProcessHeap(), 0, ptr, ((nitems) * sizeof(type)))
|
||||
//#define STORM_FREE(ptr) HeapFree(GetProcessHeap(), 0, ptr)
|
||||
//
|
||||
//#else
|
||||
|
||||
#define STORM_ALLOC(type, nitems) (type *)malloc((nitems) * sizeof(type))
|
||||
#define STORM_REALLOC(type, ptr, nitems) (type *)realloc(ptr, ((nitems) * sizeof(type)))
|
||||
#define STORM_FREE(ptr) free(ptr)
|
||||
|
||||
//#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StormLib internal global variables
|
||||
|
||||
extern DWORD g_dwMpqSignature; // Marker for MPQ header
|
||||
extern DWORD g_dwHashTableKey; // Key for hash table
|
||||
extern DWORD g_dwBlockTableKey; // Key for block table
|
||||
extern LCID g_lcFileLocale; // Preferred file locale and platform
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Conversion to uppercase/lowercase (and "/" to "\")
|
||||
|
||||
extern unsigned char AsciiToLowerTable[256];
|
||||
extern unsigned char AsciiToUpperTable[256];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Safe string functions
|
||||
|
||||
template <typename XCHAR, typename XINT>
|
||||
XCHAR * IntToString(XCHAR * szBuffer, size_t cchMaxChars, XINT nValue, size_t nDigitCount = 0)
|
||||
{
|
||||
XCHAR * szBufferEnd = szBuffer + cchMaxChars - 1;
|
||||
XCHAR szNumberRev[0x20];
|
||||
size_t nLength = 0;
|
||||
|
||||
// Always put the first digit
|
||||
szNumberRev[nLength++] = (XCHAR)(nValue % 10) + '0';
|
||||
nValue /= 10;
|
||||
|
||||
// Continue as long as we have non-zero
|
||||
while(nValue != 0)
|
||||
{
|
||||
szNumberRev[nLength++] = (XCHAR)(nValue % 10) + '0';
|
||||
nValue /= 10;
|
||||
}
|
||||
|
||||
// Fill zeros, if needed
|
||||
while(szBuffer < szBufferEnd && nLength < nDigitCount)
|
||||
{
|
||||
*szBuffer++ = '0';
|
||||
nDigitCount--;
|
||||
}
|
||||
|
||||
// Fill the buffer
|
||||
while(szBuffer < szBufferEnd && nLength > 0)
|
||||
{
|
||||
nLength--;
|
||||
*szBuffer++ = szNumberRev[nLength];
|
||||
}
|
||||
|
||||
// Terminate the number with zeros
|
||||
szBuffer[0] = 0;
|
||||
return szBuffer;
|
||||
}
|
||||
|
||||
char * StringCopy(char * szTarget, size_t cchTarget, const char * szSource);
|
||||
void StringCat(char * szTarget, size_t cchTargetMax, const char * szSource);
|
||||
void StringCreatePseudoFileName(char * szBuffer, size_t cchMaxChars, unsigned int nIndex, const char * szExtension);
|
||||
|
||||
#ifdef _UNICODE
|
||||
void StringCopy(TCHAR * szTarget, size_t cchTarget, const char * szSource);
|
||||
void StringCopy(char * szTarget, size_t cchTarget, const TCHAR * szSource);
|
||||
void StringCopy(TCHAR * szTarget, size_t cchTarget, const TCHAR * szSource);
|
||||
void StringCat(TCHAR * szTarget, size_t cchTargetMax, const TCHAR * szSource);
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Encryption and decryption functions
|
||||
|
||||
#define MPQ_HASH_TABLE_INDEX 0x000
|
||||
#define MPQ_HASH_NAME_A 0x100
|
||||
#define MPQ_HASH_NAME_B 0x200
|
||||
#define MPQ_HASH_FILE_KEY 0x300
|
||||
#define MPQ_HASH_KEY2_MIX 0x400
|
||||
|
||||
DWORD HashString(const char * szFileName, DWORD dwHashType);
|
||||
DWORD HashStringSlash(const char * szFileName, DWORD dwHashType);
|
||||
DWORD HashStringLower(const char * szFileName, DWORD dwHashType);
|
||||
|
||||
void InitializeMpqCryptography();
|
||||
|
||||
DWORD GetNearestPowerOfTwo(DWORD dwFileCount);
|
||||
|
||||
bool IsPseudoFileName(const char * szFileName, LPDWORD pdwFileIndex);
|
||||
ULONGLONG HashStringJenkins(const char * szFileName);
|
||||
|
||||
DWORD GetDefaultSpecialFileFlags(DWORD dwFileSize, USHORT wFormatVersion);
|
||||
|
||||
void EncryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey);
|
||||
void DecryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey);
|
||||
|
||||
DWORD DetectFileKeyBySectorSize(LPDWORD EncryptedData, DWORD dwSectorSize, DWORD dwSectorOffsLen);
|
||||
DWORD DetectFileKeyByContent(void * pvEncryptedData, DWORD dwSectorSize, DWORD dwFileSize);
|
||||
DWORD DecryptFileKey(const char * szFileName, ULONGLONG MpqPos, DWORD dwFileSize, DWORD dwFlags);
|
||||
|
||||
bool IsValidMD5(LPBYTE pbMd5);
|
||||
bool IsValidSignature(LPBYTE pbSignature);
|
||||
bool VerifyDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5);
|
||||
void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_hash);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle validation functions
|
||||
|
||||
TMPQArchive * IsValidMpqHandle(HANDLE hMpq);
|
||||
TMPQFile * IsValidFileHandle(HANDLE hFile);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Support for MPQ file tables
|
||||
|
||||
ULONGLONG GetFileOffsetMask(TMPQArchive * ha);
|
||||
ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset);
|
||||
ULONGLONG CalculateRawSectorOffset(TMPQFile * hf, DWORD dwSectorOffset);
|
||||
|
||||
DWORD ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG FileSize, DWORD dwFlags, MTYPE MapType);
|
||||
|
||||
bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash);
|
||||
|
||||
TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcFileLocale);
|
||||
TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName);
|
||||
TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash);
|
||||
TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry, LCID lcFileLocale);
|
||||
|
||||
TMPQExtHeader * LoadExtTable(TMPQArchive * ha, ULONGLONG ByteOffset, size_t Size, DWORD dwSignature, DWORD dwKey);
|
||||
TMPQHetTable * LoadHetTable(TMPQArchive * ha);
|
||||
TMPQBetTable * LoadBetTable(TMPQArchive * ha);
|
||||
|
||||
TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool bDontFixEntries = false);
|
||||
TMPQBlock * TranslateBlockTable(TMPQArchive * ha, ULONGLONG * pcbTableSize, bool * pbNeedHiBlockTable);
|
||||
|
||||
ULONGLONG FindFreeMpqSpace(TMPQArchive * ha);
|
||||
|
||||
// Functions that load the HET and BET tables
|
||||
DWORD CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize);
|
||||
DWORD LoadAnyHashTable(TMPQArchive * ha);
|
||||
DWORD BuildFileTable(TMPQArchive * ha);
|
||||
DWORD DefragmentFileTable(TMPQArchive * ha);
|
||||
|
||||
DWORD CreateFileTable(TMPQArchive * ha, DWORD dwFileTableSize);
|
||||
DWORD RebuildHetTable(TMPQArchive * ha);
|
||||
DWORD RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize);
|
||||
DWORD SaveMPQTables(TMPQArchive * ha);
|
||||
|
||||
TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwHashBitSize, LPBYTE pbSrcData);
|
||||
void FreeHetTable(TMPQHetTable * pHetTable);
|
||||
|
||||
TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount);
|
||||
void FreeBetTable(TMPQBetTable * pBetTable);
|
||||
|
||||
// Functions for finding files in the file table
|
||||
TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex = NULL);
|
||||
TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex);
|
||||
|
||||
// Allocates file name in the file entry
|
||||
void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szFileName);
|
||||
|
||||
// Allocates new file entry in the MPQ tables. Reuses existing, if possible
|
||||
TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex);
|
||||
DWORD RenameFileEntry(TMPQArchive * ha, TMPQFile * hf, const char * szNewFileName);
|
||||
DWORD DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf);
|
||||
|
||||
// Invalidates entries for (listfile) and (attributes)
|
||||
void InvalidateInternalFiles(TMPQArchive * ha);
|
||||
|
||||
// Retrieves information about the strong signature
|
||||
bool QueryMpqSignatureInfo(TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSignatureInfo);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Support for alternate file formats (SBaseSubTypes.cpp)
|
||||
|
||||
DWORD ConvertSqpHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
|
||||
TMPQHash * LoadSqpHashTable(TMPQArchive * ha);
|
||||
TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha);
|
||||
|
||||
DWORD ConvertMpkHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
|
||||
void DecryptMpkTable(void * pvMpkTable, size_t cbSize);
|
||||
TMPQHash * LoadMpkHashTable(TMPQArchive * ha);
|
||||
TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha);
|
||||
int SCompDecompressMpk(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Common functions - MPQ File
|
||||
|
||||
TMPQFile * CreateFileHandle(TMPQArchive * ha, TFileEntry * pFileEntry);
|
||||
TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize);
|
||||
void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, LPBYTE pbTableHash, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey, DWORD * PtrRealTableSize);
|
||||
DWORD AllocateSectorBuffer(TMPQFile * hf);
|
||||
DWORD AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile);
|
||||
DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile);
|
||||
DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile);
|
||||
DWORD WritePatchInfo(TMPQFile * hf);
|
||||
DWORD WriteSectorOffsets(TMPQFile * hf);
|
||||
DWORD WriteSectorChecksums(TMPQFile * hf);
|
||||
DWORD WriteMemDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, void * pvRawData, DWORD dwRawDataSize, DWORD dwChunkSize, LPDWORD pcbTotalSize);
|
||||
DWORD WriteMpqDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, DWORD dwRawDataSize, DWORD dwChunkSize);
|
||||
void FreeFileHandle(TMPQFile *& hf);
|
||||
void FreeArchiveHandle(TMPQArchive *& ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Patch functions
|
||||
|
||||
// Structure used for the patching process
|
||||
typedef struct _TMPQPatcher
|
||||
{
|
||||
BYTE this_md5[MD5_DIGEST_SIZE]; // MD5 of the current file state
|
||||
LPBYTE pbFileData1; // Primary working buffer
|
||||
LPBYTE pbFileData2; // Secondary working buffer
|
||||
DWORD cbMaxFileData; // Maximum allowed size of the patch data
|
||||
DWORD cbFileData; // Current size of the result data
|
||||
DWORD nCounter; // Counter of the patch process
|
||||
|
||||
} TMPQPatcher;
|
||||
|
||||
bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize);
|
||||
DWORD Patch_InitPatcher(TMPQPatcher * pPatcher, TMPQFile * hf);
|
||||
DWORD Patch_Process(TMPQPatcher * pPatcher, TMPQFile * hf);
|
||||
void Patch_Finalize(TMPQPatcher * pPatcher);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utility functions
|
||||
|
||||
bool IsInternalMpqFileName(const char * szFileName);
|
||||
|
||||
template <typename XCHAR>
|
||||
const XCHAR * GetPlainFileName(const XCHAR * szFileName)
|
||||
{
|
||||
const XCHAR * szPlainName = szFileName;
|
||||
|
||||
while(*szFileName != 0)
|
||||
{
|
||||
if(*szFileName == '\\' || *szFileName == '/')
|
||||
szPlainName = szFileName + 1;
|
||||
szFileName++;
|
||||
}
|
||||
|
||||
return szPlainName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Internal support for MPQ modifications
|
||||
|
||||
DWORD SFileAddFile_Init(
|
||||
TMPQArchive * ha,
|
||||
const char * szArchivedName,
|
||||
ULONGLONG ft,
|
||||
DWORD dwFileSize,
|
||||
LCID lcFileLocale,
|
||||
DWORD dwFlags,
|
||||
TMPQFile ** phf
|
||||
);
|
||||
|
||||
DWORD SFileAddFile_Init(
|
||||
TMPQArchive * ha,
|
||||
TMPQFile * hfSrc,
|
||||
TMPQFile ** phf
|
||||
);
|
||||
|
||||
DWORD SFileAddFile_Write(
|
||||
TMPQFile * hf,
|
||||
const void * pvData,
|
||||
DWORD dwSize,
|
||||
DWORD dwCompression
|
||||
);
|
||||
|
||||
DWORD SFileAddFile_Finish(
|
||||
TMPQFile * hf
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attributes support
|
||||
|
||||
DWORD SAttrLoadAttributes(TMPQArchive * ha);
|
||||
DWORD SAttrFileSaveToMpq(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile functions
|
||||
|
||||
DWORD SListFileSaveToMpq(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Weak signature support
|
||||
|
||||
DWORD SSignFileCreate(TMPQArchive * ha);
|
||||
DWORD SSignFileFinish(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dump data support
|
||||
|
||||
#ifdef __STORMLIB_DUMP_DATA__
|
||||
|
||||
void DumpMpqHeader(TMPQHeader * pHeader);
|
||||
void DumpHashTable(TMPQHash * pHashTable, DWORD dwHashTableSize);
|
||||
void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable);
|
||||
void DumpFileTable(TFileEntry * pFileTable, DWORD dwFileTableSize);
|
||||
|
||||
#else
|
||||
|
||||
#define DumpMpqHeader(h) /* */
|
||||
#define DumpHashTable(t, s) /* */
|
||||
#define DumpHetAndBetTable(t, s) /* */
|
||||
#define DumpFileTable(t, s) /* */
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __STORMCOMMON_H__
|
||||
|
||||
74
vendor/stormlib-9/src/StormLib.exp
vendored
Normal file
74
vendor/stormlib-9/src/StormLib.exp
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
#
|
||||
# Export file for Mac OS X
|
||||
# Copyright (c) 2009 Sam Wilkins
|
||||
# swilkins1337@gmail.com
|
||||
#
|
||||
|
||||
_SFileSetLocale
|
||||
_SFileGetLocale
|
||||
|
||||
_SFileOpenArchive
|
||||
_SFileCreateArchive
|
||||
_SFileFlushArchive
|
||||
_SFileCloseArchive
|
||||
|
||||
_SFileAddListFile
|
||||
|
||||
_SFileSetCompactCallback
|
||||
_SFileCompactArchive
|
||||
|
||||
_SFileGetMaxFileCount
|
||||
_SFileSetMaxFileCount
|
||||
|
||||
_SFileGetAttributes
|
||||
_SFileSetAttributes
|
||||
_SFileUpdateFileAttributes
|
||||
|
||||
_SFileOpenPatchArchive
|
||||
_SFileIsPatchedArchive
|
||||
|
||||
_SFileOpenFileEx
|
||||
_SFileGetFileSize
|
||||
_SFileSetFilePointer
|
||||
_SFileReadFile
|
||||
_SFileCloseFile
|
||||
|
||||
_SFileHasFile
|
||||
_SFileGetFileName
|
||||
_SFileGetFileInfo
|
||||
|
||||
_SFileExtractFile
|
||||
|
||||
_SFileVerifyFile
|
||||
_SFileVerifyRawData
|
||||
_SFileVerifyArchive
|
||||
|
||||
_SFileFindFirstFile
|
||||
_SFileFindNextFile
|
||||
_SFileFindClose
|
||||
|
||||
_SListFileFindFirstFile
|
||||
_SListFileFindNextFile
|
||||
_SListFileFindClose
|
||||
|
||||
_SFileEnumLocales
|
||||
|
||||
_SFileCreateFile
|
||||
_SFileWriteFile
|
||||
_SFileFinishFile
|
||||
_SFileAddFileEx
|
||||
_SFileAddFile
|
||||
_SFileAddWave
|
||||
_SFileRemoveFile
|
||||
_SFileRenameFile
|
||||
_SFileSetFileLocale
|
||||
_SFileSetDataCompression
|
||||
_SFileSetAddFileCallback
|
||||
|
||||
_SCompImplode
|
||||
_SCompExplode
|
||||
_SCompCompress
|
||||
_SCompDecompress
|
||||
|
||||
_SetLastError
|
||||
_GetLastError
|
||||
1157
vendor/stormlib-9/src/StormLib.h
vendored
Normal file
1157
vendor/stormlib-9/src/StormLib.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
473
vendor/stormlib-9/src/StormPort.h
vendored
Normal file
473
vendor/stormlib-9/src/StormPort.h
vendored
Normal file
@ -0,0 +1,473 @@
|
||||
/*****************************************************************************/
|
||||
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Portability module for the StormLib library. Contains a wrapper symbols */
|
||||
/* to make the compilation under Linux work */
|
||||
/* */
|
||||
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
|
||||
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
|
||||
/* Computer: whiplash.flachland-chemnitz.de */
|
||||
/* System: Linux 2.4.0 on i686 */
|
||||
/* */
|
||||
/* Author: Sam Wilkins <swilkins1337@gmail.com> */
|
||||
/* System: Mac OS X and port to big endian processor */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 29.01.01 1.00 Mar Created */
|
||||
/* 24.03.03 1.01 Lad Some cosmetic changes */
|
||||
/* 12.11.03 1.02 Dan Macintosh compatibility */
|
||||
/* 24.07.04 1.03 Sam Mac OS X compatibility */
|
||||
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
|
||||
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
|
||||
/* 17.10.12 1.05 Lad Moved error codes so they don't overlap with errno.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMPORT_H__
|
||||
#define __STORMPORT_H__
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define bool char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for Windows
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(_WIN32)
|
||||
|
||||
// In MSVC 8.0, there are some functions declared as deprecated.
|
||||
#if _MSC_VER >= 1400
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Suppress definitions of `min` and `max` macros by <windows.h>:
|
||||
#define NOMINMAX 1
|
||||
#include <windows.h>
|
||||
|
||||
#include <wininet.h>
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
|
||||
#ifdef _WIN64
|
||||
#define STORMLIB_64BIT
|
||||
#else
|
||||
#define STORMLIB_32BIT
|
||||
#endif
|
||||
|
||||
#define STORMLIB_CDECL __cdecl
|
||||
|
||||
#define STORMLIB_WINDOWS
|
||||
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for Mac
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API
|
||||
|
||||
// Macintosh
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Support for PowerPC on Max OS X
|
||||
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
|
||||
#include <stdint.h>
|
||||
#include <CoreFoundation/CFByteOrder.h>
|
||||
#endif
|
||||
|
||||
#define PKEXPORT
|
||||
|
||||
#ifndef __SYS_ZLIB
|
||||
#define __SYS_ZLIB
|
||||
#endif
|
||||
|
||||
#ifndef __SYS_BZLIB
|
||||
#define __SYS_BZLIB
|
||||
#endif
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define STORMLIB_MAC
|
||||
#define STORMLIB_HAS_MMAP // Indicate that we have mmap support
|
||||
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for HAIKU platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__HAIKU__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_HAIKU
|
||||
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for AMIGA platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__AMIGA__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_AMIGA
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for Switch platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__SWITCH__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_SWITCH
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for 3DS platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__3DS__)
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_CTR
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for Vita platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__vita__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_VITA
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines for Wii U platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__WIIU__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#undef STORMLIB_LITTLE_ENDIAN // Wii U is always big endian
|
||||
|
||||
#define STORMLIB_MAC // Use Mac compatible code
|
||||
#define STORMLIB_WIIU
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Assumption: If the platform is not defined, assume a Linux-like platform
|
||||
|
||||
#if !defined(STORMLIB_PLATFORM_DEFINED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define STORMLIB_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// Platforms with mmap support
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <sys/mman.h>
|
||||
#define STORMLIB_HAS_MMAP
|
||||
#endif
|
||||
|
||||
#define STORMLIB_LINUX
|
||||
#define STORMLIB_PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definition of Windows-specific types for non-Windows platforms
|
||||
|
||||
#ifndef STORMLIB_WINDOWS
|
||||
#if __LP64__
|
||||
#define STORMLIB_64BIT
|
||||
#else
|
||||
#define STORMLIB_32BIT
|
||||
#endif
|
||||
|
||||
// __cdecl meand nothing on non-Windows
|
||||
#define STORMLIB_CDECL /* */
|
||||
|
||||
// Typedefs for ANSI C
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short USHORT;
|
||||
typedef int LONG;
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned long DWORD_PTR;
|
||||
typedef long LONG_PTR;
|
||||
typedef long INT_PTR;
|
||||
typedef long long LONGLONG;
|
||||
typedef unsigned long long ULONGLONG;
|
||||
typedef void * HANDLE;
|
||||
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
|
||||
typedef char TCHAR;
|
||||
typedef unsigned int LCID;
|
||||
typedef LONG * PLONG;
|
||||
typedef DWORD * LPDWORD;
|
||||
typedef BYTE * LPBYTE;
|
||||
typedef const char * LPCTSTR;
|
||||
typedef const char * LPCSTR;
|
||||
typedef char * LPTSTR;
|
||||
typedef char * LPSTR;
|
||||
|
||||
#ifdef STORMLIB_32BIT
|
||||
#define _LZMA_UINT32_IS_ULONG
|
||||
#endif
|
||||
|
||||
// Some Windows-specific defines
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
#define WINAPI
|
||||
|
||||
#define FILE_BEGIN SEEK_SET
|
||||
#define FILE_CURRENT SEEK_CUR
|
||||
#define FILE_END SEEK_END
|
||||
|
||||
#define _T(x) x
|
||||
#define _tcslen strlen
|
||||
#define _tcscpy strcpy
|
||||
#define _tcscat strcat
|
||||
#define _tcschr strchr
|
||||
#define _tcsrchr strrchr
|
||||
#define _tcsstr strstr
|
||||
#define _tcsnicmp strncasecmp
|
||||
#define _tprintf printf
|
||||
#define _stprintf sprintf
|
||||
#define _tremove remove
|
||||
#define _tmain main
|
||||
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
#define _tcsicmp strcasecmp
|
||||
#define _tcsnicmp strncasecmp
|
||||
|
||||
#endif // !STORMLIB_WINDOWS
|
||||
|
||||
// 64-bit calls are supplied by "normal" calls on Mac
|
||||
#if defined(STORMLIB_MAC)
|
||||
#define stat64 stat
|
||||
#define fstat64 fstat
|
||||
#define lseek64 lseek
|
||||
#define ftruncate64 ftruncate
|
||||
#define off64_t off_t
|
||||
#define O_LARGEFILE 0
|
||||
#endif
|
||||
|
||||
// Platform-specific error codes for non-Windows platforms
|
||||
#ifndef ERROR_SUCCESS
|
||||
#define ERROR_SUCCESS 0
|
||||
#define ERROR_FILE_NOT_FOUND ENOENT
|
||||
#define ERROR_ACCESS_DENIED EPERM
|
||||
#define ERROR_INVALID_HANDLE EBADF
|
||||
#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
|
||||
#define ERROR_NOT_SUPPORTED ENOTSUP
|
||||
#define ERROR_INVALID_PARAMETER EINVAL
|
||||
#define ERROR_NEGATIVE_SEEK ESPIPE
|
||||
#define ERROR_DISK_FULL ENOSPC
|
||||
#define ERROR_ALREADY_EXISTS EEXIST
|
||||
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
|
||||
#define ERROR_BAD_FORMAT 1000 // No such error code under Linux
|
||||
#define ERROR_NO_MORE_FILES 1001 // No such error code under Linux
|
||||
#define ERROR_HANDLE_EOF 1002 // No such error code under Linux
|
||||
#define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux
|
||||
#define ERROR_FILE_CORRUPT 1004 // No such error code under Linux
|
||||
#endif
|
||||
|
||||
// Macros that can sometimes be missing
|
||||
#ifndef _countof
|
||||
#define _countof(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Swapping functions
|
||||
|
||||
#ifdef STORMLIB_LITTLE_ENDIAN
|
||||
#define BSWAP_INT16_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT16_SIGNED(a) (a)
|
||||
#define BSWAP_INT32_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT32_SIGNED(a) (a)
|
||||
#define BSWAP_INT64_SIGNED(a) (a)
|
||||
#define BSWAP_INT64_UNSIGNED(a) (a)
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
|
||||
#define BSWAP_ARRAY64_UNSIGNED(a,b) {}
|
||||
#define BSWAP_PART_HEADER(a) {}
|
||||
#define BSWAP_TMPQHEADER(a,b) {}
|
||||
#define BSWAP_TMPKHEADER(a) {}
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int16_t SwapInt16(uint16_t);
|
||||
uint16_t SwapUInt16(uint16_t);
|
||||
int32_t SwapInt32(uint32_t);
|
||||
uint32_t SwapUInt32(uint32_t);
|
||||
int64_t SwapInt64(uint64_t);
|
||||
uint64_t SwapUInt64(uint64_t);
|
||||
void ConvertUInt16Buffer(void * ptr, size_t length);
|
||||
void ConvertUInt32Buffer(void * ptr, size_t length);
|
||||
void ConvertUInt64Buffer(void * ptr, size_t length);
|
||||
void ConvertTMPQUserData(void *userData);
|
||||
void ConvertTMPQHeader(void *header, uint16_t wPart);
|
||||
void ConvertTMPKHeader(void *header);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define BSWAP_INT16_SIGNED(a) SwapInt16((a))
|
||||
#define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
|
||||
#define BSWAP_INT32_SIGNED(a) SwapInt32((a))
|
||||
#define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
|
||||
#define BSWAP_INT64_SIGNED(a) SwapInt64((a))
|
||||
#define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
|
||||
#define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
|
||||
#define BSWAP_TMPQHEADER(a,b) ConvertTMPQHeader((a),(b))
|
||||
#define BSWAP_TMPKHEADER(a) ConvertTMPKHeader((a))
|
||||
#endif
|
||||
|
||||
#endif // __STORMPORT_H__
|
||||
539
vendor/stormlib-9/src/adpcm/adpcm.cpp
vendored
Normal file
539
vendor/stormlib-9/src/adpcm/adpcm.cpp
vendored
Normal file
@ -0,0 +1,539 @@
|
||||
/*****************************************************************************/
|
||||
/* adpcm.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This module contains implementation of adpcm decompression method used by */
|
||||
/* Storm.dll to decompress WAVE files. Thanks to Tom Amigo for releasing */
|
||||
/* his sources. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
|
||||
/* 20.05.03 2.00 Lad Added compression */
|
||||
/* 19.11.03 2.01 Dan Big endian handling */
|
||||
/* 10.01.13 3.00 Lad Refactored, beautified, documented :-) */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "adpcm.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables necessary dor decompression
|
||||
|
||||
static const int NextStepTable[] =
|
||||
{
|
||||
-1, 0, -1, 4, -1, 2, -1, 6,
|
||||
-1, 1, -1, 5, -1, 3, -1, 7,
|
||||
-1, 1, -1, 5, -1, 3, -1, 7,
|
||||
-1, 2, -1, 4, -1, 6, -1, 8
|
||||
};
|
||||
|
||||
static const int StepSizeTable[] =
|
||||
{
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
16, 17, 19, 21, 23, 25, 28, 31,
|
||||
34, 37, 41, 45, 50, 55, 60, 66,
|
||||
73, 80, 88, 97, 107, 118, 130, 143,
|
||||
157, 173, 190, 209, 230, 253, 279, 307,
|
||||
337, 371, 408, 449, 494, 544, 598, 658,
|
||||
724, 796, 876, 963, 1060, 1166, 1282, 1411,
|
||||
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
|
||||
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
||||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
|
||||
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
||||
32767
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper class for writing output ADPCM data
|
||||
|
||||
class TADPCMStream
|
||||
{
|
||||
public:
|
||||
|
||||
TADPCMStream(void * pvBuffer, size_t cbBuffer)
|
||||
{
|
||||
pbBufferEnd = (unsigned char *)pvBuffer + cbBuffer;
|
||||
pbBuffer = (unsigned char *)pvBuffer;
|
||||
}
|
||||
|
||||
bool ReadByteSample(unsigned char & ByteSample)
|
||||
{
|
||||
// Check if there is enough space in the buffer
|
||||
if(pbBuffer >= pbBufferEnd)
|
||||
return false;
|
||||
|
||||
ByteSample = *pbBuffer++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteByteSample(unsigned char ByteSample)
|
||||
{
|
||||
// Check if there is enough space in the buffer
|
||||
if(pbBuffer >= pbBufferEnd)
|
||||
return false;
|
||||
|
||||
*pbBuffer++ = ByteSample;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadWordSample(short & OneSample)
|
||||
{
|
||||
// Check if we have enough space in the output buffer
|
||||
if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short))
|
||||
return false;
|
||||
|
||||
// Write the sample
|
||||
OneSample = pbBuffer[0] + (((short)pbBuffer[1]) << 0x08);
|
||||
pbBuffer += sizeof(short);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteWordSample(short OneSample)
|
||||
{
|
||||
// Check if we have enough space in the output buffer
|
||||
if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short))
|
||||
return false;
|
||||
|
||||
// Write the sample
|
||||
*pbBuffer++ = (unsigned char)(OneSample & 0xFF);
|
||||
*pbBuffer++ = (unsigned char)(OneSample >> 0x08);
|
||||
return true;
|
||||
}
|
||||
|
||||
int LengthProcessed(void * pvOutBuffer)
|
||||
{
|
||||
return (int)((unsigned char *)pbBuffer - (unsigned char *)pvOutBuffer);
|
||||
}
|
||||
|
||||
unsigned char * pbBufferEnd;
|
||||
unsigned char * pbBuffer;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static inline short GetNextStepIndex(int StepIndex, unsigned int EncodedSample)
|
||||
{
|
||||
// Get the next step index
|
||||
StepIndex = StepIndex + NextStepTable[EncodedSample & 0x1F];
|
||||
|
||||
// Don't make the step index overflow
|
||||
if(StepIndex < 0)
|
||||
StepIndex = 0;
|
||||
else if(StepIndex > 88)
|
||||
StepIndex = 88;
|
||||
|
||||
return (short)StepIndex;
|
||||
}
|
||||
|
||||
static inline int UpdatePredictedSample(int PredictedSample, int EncodedSample, int Difference, int BitMask = 0x40)
|
||||
{
|
||||
// Is the sign bit set?
|
||||
if(EncodedSample & BitMask)
|
||||
{
|
||||
PredictedSample -= Difference;
|
||||
if(PredictedSample <= -32768)
|
||||
PredictedSample = -32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
PredictedSample += Difference;
|
||||
if(PredictedSample >= 32767)
|
||||
PredictedSample = 32767;
|
||||
}
|
||||
|
||||
return PredictedSample;
|
||||
}
|
||||
|
||||
static inline int DecodeSample(int PredictedSample, int EncodedSample, int StepSize, int Difference)
|
||||
{
|
||||
if(EncodedSample & 0x01)
|
||||
Difference += (StepSize >> 0);
|
||||
|
||||
if(EncodedSample & 0x02)
|
||||
Difference += (StepSize >> 1);
|
||||
|
||||
if(EncodedSample & 0x04)
|
||||
Difference += (StepSize >> 2);
|
||||
|
||||
if(EncodedSample & 0x08)
|
||||
Difference += (StepSize >> 3);
|
||||
|
||||
if(EncodedSample & 0x10)
|
||||
Difference += (StepSize >> 4);
|
||||
|
||||
if(EncodedSample & 0x20)
|
||||
Difference += (StepSize >> 5);
|
||||
|
||||
return UpdatePredictedSample(PredictedSample, EncodedSample, Difference);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compression routine
|
||||
|
||||
int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount, int CompressionLevel)
|
||||
{
|
||||
TADPCMStream os(pvOutBuffer, cbOutBuffer); // The output stream
|
||||
TADPCMStream is(pvInBuffer, cbInBuffer); // The input stream
|
||||
unsigned char BitShift = (unsigned char)(CompressionLevel - 1);
|
||||
short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT];// Predicted samples for each channel
|
||||
short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Step indexes for each channel
|
||||
short InputSample; // Input sample for the current channel
|
||||
int TotalStepSize;
|
||||
int ChannelIndex;
|
||||
int AbsDifference;
|
||||
int Difference;
|
||||
int MaxBitMask;
|
||||
int StepSize;
|
||||
|
||||
// First byte in the output stream contains zero. The second one contains the compression level
|
||||
os.WriteByteSample(0);
|
||||
if(!os.WriteByteSample(BitShift))
|
||||
return 2;
|
||||
|
||||
// Set the initial step index for each channel
|
||||
PredictedSamples[0] = PredictedSamples[1] = 0;
|
||||
StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
|
||||
|
||||
// Next, InitialSample value for each channel follows
|
||||
for(int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
// Get the initial sample from the input stream
|
||||
if(!is.ReadWordSample(InputSample))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
|
||||
// Store the initial sample to our sample array
|
||||
PredictedSamples[i] = InputSample;
|
||||
|
||||
// Also store the loaded sample to the output stream
|
||||
if(!os.WriteWordSample(InputSample))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
|
||||
// Get the initial index
|
||||
ChannelIndex = ChannelCount - 1;
|
||||
|
||||
// Now keep reading the input data as long as there is something in the input buffer
|
||||
while(is.ReadWordSample(InputSample))
|
||||
{
|
||||
int EncodedSample = 0;
|
||||
|
||||
// If we have two channels, we need to flip the channel index
|
||||
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
|
||||
|
||||
// Get the difference from the previous sample.
|
||||
// If the difference is negative, set the sign bit to the encoded sample
|
||||
AbsDifference = InputSample - PredictedSamples[ChannelIndex];
|
||||
if(AbsDifference < 0)
|
||||
{
|
||||
AbsDifference = -AbsDifference;
|
||||
EncodedSample |= 0x40;
|
||||
}
|
||||
|
||||
// If the difference is too low (higher that difference treshold),
|
||||
// write a step index modifier marker
|
||||
StepSize = StepSizeTable[StepIndexes[ChannelIndex]];
|
||||
if(AbsDifference < (StepSize >> CompressionLevel))
|
||||
{
|
||||
if(StepIndexes[ChannelIndex] != 0)
|
||||
StepIndexes[ChannelIndex]--;
|
||||
|
||||
os.WriteByteSample(0x80);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the difference is too high, write marker that
|
||||
// indicates increase in step size
|
||||
while(AbsDifference > (StepSize << 1))
|
||||
{
|
||||
if(StepIndexes[ChannelIndex] >= 0x58)
|
||||
break;
|
||||
|
||||
// Modify the step index
|
||||
StepIndexes[ChannelIndex] += 8;
|
||||
if(StepIndexes[ChannelIndex] > 0x58)
|
||||
StepIndexes[ChannelIndex] = 0x58;
|
||||
|
||||
// Write the "modify step index" marker
|
||||
StepSize = StepSizeTable[StepIndexes[ChannelIndex]];
|
||||
os.WriteByteSample(0x81);
|
||||
}
|
||||
|
||||
// Get the limit bit value
|
||||
MaxBitMask = (1 << (BitShift - 1));
|
||||
MaxBitMask = (MaxBitMask > 0x20) ? 0x20 : MaxBitMask;
|
||||
Difference = StepSize >> BitShift;
|
||||
TotalStepSize = 0;
|
||||
|
||||
for(int BitVal = 0x01; BitVal <= MaxBitMask; BitVal <<= 1)
|
||||
{
|
||||
if((TotalStepSize + StepSize) <= AbsDifference)
|
||||
{
|
||||
TotalStepSize += StepSize;
|
||||
EncodedSample |= BitVal;
|
||||
}
|
||||
StepSize >>= 1;
|
||||
}
|
||||
|
||||
PredictedSamples[ChannelIndex] = (short)UpdatePredictedSample(PredictedSamples[ChannelIndex],
|
||||
EncodedSample,
|
||||
Difference + TotalStepSize);
|
||||
// Write the encoded sample to the output stream
|
||||
if(!os.WriteByteSample((unsigned char)EncodedSample))
|
||||
break;
|
||||
|
||||
// Calculates the step index to use for the next encode
|
||||
StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndexes[ChannelIndex], EncodedSample);
|
||||
}
|
||||
}
|
||||
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Decompression routine
|
||||
|
||||
int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount)
|
||||
{
|
||||
TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream
|
||||
TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream
|
||||
unsigned char EncodedSample;
|
||||
unsigned char BitShift;
|
||||
short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT]; // Predicted sample for each channel
|
||||
short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Predicted step index for each channel
|
||||
int ChannelIndex; // Current channel index
|
||||
|
||||
// Initialize the StepIndex for each channel
|
||||
PredictedSamples[0] = PredictedSamples[1] = 0;
|
||||
StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
|
||||
|
||||
// The first byte is always zero, the second one contains bit shift (compression level - 1)
|
||||
is.ReadByteSample(BitShift);
|
||||
is.ReadByteSample(BitShift);
|
||||
|
||||
// Next, InitialSample value for each channel follows
|
||||
for(int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
// Get the initial sample from the input stream
|
||||
short InitialSample;
|
||||
|
||||
// Attempt to read the initial sample
|
||||
if(!is.ReadWordSample(InitialSample))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
|
||||
// Store the initial sample to our sample array
|
||||
PredictedSamples[i] = InitialSample;
|
||||
|
||||
// Also store the loaded sample to the output stream
|
||||
if(!os.WriteWordSample(InitialSample))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
|
||||
// Get the initial index
|
||||
ChannelIndex = ChannelCount - 1;
|
||||
|
||||
// Keep reading as long as there is something in the input buffer
|
||||
while(is.ReadByteSample(EncodedSample))
|
||||
{
|
||||
// If we have two channels, we need to flip the channel index
|
||||
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
|
||||
|
||||
if(EncodedSample == 0x80)
|
||||
{
|
||||
if(StepIndexes[ChannelIndex] != 0)
|
||||
StepIndexes[ChannelIndex]--;
|
||||
|
||||
if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
else if(EncodedSample == 0x81)
|
||||
{
|
||||
// Modify the step index
|
||||
StepIndexes[ChannelIndex] += 8;
|
||||
if(StepIndexes[ChannelIndex] > 0x58)
|
||||
StepIndexes[ChannelIndex] = 0x58;
|
||||
|
||||
// Next pass, keep going on the same channel
|
||||
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
int StepIndex = StepIndexes[ChannelIndex];
|
||||
int StepSize = StepSizeTable[StepIndex];
|
||||
|
||||
// Encode one sample
|
||||
PredictedSamples[ChannelIndex] = (short)DecodeSample(PredictedSamples[ChannelIndex],
|
||||
EncodedSample,
|
||||
StepSize,
|
||||
StepSize >> BitShift);
|
||||
|
||||
// Write the decoded sample to the output stream
|
||||
if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
|
||||
break;
|
||||
|
||||
// Calculates the step index to use for the next encode
|
||||
StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndex, EncodedSample);
|
||||
}
|
||||
}
|
||||
|
||||
// Return total bytes written since beginning of the output buffer
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ADPCM decompression present in Starcraft I BETA
|
||||
|
||||
typedef struct _ADPCM_DATA
|
||||
{
|
||||
const unsigned int * pValues;
|
||||
int BitCount;
|
||||
int field_8;
|
||||
int field_C;
|
||||
int field_10;
|
||||
|
||||
} ADPCM_DATA, *PADPCM_DATA;
|
||||
|
||||
static const unsigned int adpcm_values_2[] = {0x33, 0x66};
|
||||
static const unsigned int adpcm_values_3[] = {0x3A, 0x3A, 0x50, 0x70};
|
||||
static const unsigned int adpcm_values_4[] = {0x3A, 0x3A, 0x3A, 0x3A, 0x4D, 0x66, 0x80, 0x9A};
|
||||
static const unsigned int adpcm_values_6[] =
|
||||
{
|
||||
0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
|
||||
0x46, 0x53, 0x60, 0x6D, 0x7A, 0x86, 0x93, 0xA0, 0xAD, 0xBA, 0xC6, 0xD3, 0xE0, 0xED, 0xFA, 0x106
|
||||
};
|
||||
|
||||
static const unsigned int * InitAdpcmData(PADPCM_DATA pData, unsigned char BitCount)
|
||||
{
|
||||
switch(BitCount)
|
||||
{
|
||||
case 2:
|
||||
pData->pValues = adpcm_values_2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pData->pValues = adpcm_values_3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
pData->pValues = adpcm_values_4;
|
||||
break;
|
||||
|
||||
default:
|
||||
pData->pValues = NULL;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
pData->pValues = adpcm_values_6;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->BitCount = BitCount;
|
||||
pData->field_C = 0x20000;
|
||||
pData->field_8 = 1 << BitCount;
|
||||
pData->field_10 = (1 << BitCount) / 2;
|
||||
return pData->pValues;
|
||||
}
|
||||
|
||||
int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount)
|
||||
{
|
||||
TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream
|
||||
TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream
|
||||
ADPCM_DATA AdpcmData;
|
||||
int LowBitValues[MAX_ADPCM_CHANNEL_COUNT];
|
||||
int UpperBits[MAX_ADPCM_CHANNEL_COUNT];
|
||||
int BitMasks[MAX_ADPCM_CHANNEL_COUNT];
|
||||
int PredictedSamples[MAX_ADPCM_CHANNEL_COUNT];
|
||||
int ChannelIndex;
|
||||
int ChannelIndexMax;
|
||||
int OutputSample;
|
||||
unsigned char BitCount;
|
||||
unsigned char EncodedSample;
|
||||
short InputValue16;
|
||||
int reg_eax;
|
||||
int Difference;
|
||||
|
||||
// The first byte contains number of bits
|
||||
if(!is.ReadByteSample(BitCount))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
if(!InitAdpcmData(&AdpcmData, BitCount))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
assert(AdpcmData.pValues != NULL);
|
||||
|
||||
// Init bit values
|
||||
for(int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
unsigned char OneByte;
|
||||
|
||||
if(!is.ReadByteSample(OneByte))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
LowBitValues[i] = OneByte & 0x01;
|
||||
UpperBits[i] = OneByte >> 1;
|
||||
}
|
||||
|
||||
//
|
||||
for(int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
if(!is.ReadWordSample(InputValue16))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
BitMasks[i] = InputValue16 << AdpcmData.BitCount;
|
||||
}
|
||||
|
||||
// Next, InitialSample value for each channel follows
|
||||
for(int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
if(!is.ReadWordSample(InputValue16))
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
|
||||
PredictedSamples[i] = InputValue16;
|
||||
os.WriteWordSample(InputValue16);
|
||||
}
|
||||
|
||||
// Get the initial index
|
||||
ChannelIndexMax = ChannelCount - 1;
|
||||
ChannelIndex = 0;
|
||||
|
||||
// Keep reading as long as there is something in the input buffer
|
||||
while(is.ReadByteSample(EncodedSample))
|
||||
{
|
||||
reg_eax = ((PredictedSamples[ChannelIndex] * 3) << 3) - PredictedSamples[ChannelIndex];
|
||||
PredictedSamples[ChannelIndex] = ((reg_eax * 10) + 0x80) >> 8;
|
||||
|
||||
Difference = (((EncodedSample >> 1) + 1) * BitMasks[ChannelIndex] + AdpcmData.field_10) >> AdpcmData.BitCount;
|
||||
|
||||
PredictedSamples[ChannelIndex] = UpdatePredictedSample(PredictedSamples[ChannelIndex], EncodedSample, Difference, 0x01);
|
||||
|
||||
BitMasks[ChannelIndex] = (AdpcmData.pValues[EncodedSample >> 1] * BitMasks[ChannelIndex] + 0x80) >> 6;
|
||||
if(BitMasks[ChannelIndex] < AdpcmData.field_8)
|
||||
BitMasks[ChannelIndex] = AdpcmData.field_8;
|
||||
|
||||
if(BitMasks[ChannelIndex] > AdpcmData.field_C)
|
||||
BitMasks[ChannelIndex] = AdpcmData.field_C;
|
||||
|
||||
reg_eax = (cbInBuffer - is.LengthProcessed(pvInBuffer)) >> ChannelIndexMax;
|
||||
OutputSample = PredictedSamples[ChannelIndex];
|
||||
if(reg_eax < UpperBits[ChannelIndex])
|
||||
{
|
||||
if(LowBitValues[ChannelIndex])
|
||||
{
|
||||
OutputSample += (UpperBits[ChannelIndex] - reg_eax);
|
||||
if(OutputSample > 32767)
|
||||
OutputSample = 32767;
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputSample += (reg_eax - UpperBits[ChannelIndex]);
|
||||
if(OutputSample < -32768)
|
||||
OutputSample = -32768;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the word sample and swap channel
|
||||
os.WriteWordSample((short)(OutputSample));
|
||||
ChannelIndex = (ChannelIndex + 1) % ChannelCount;
|
||||
}
|
||||
|
||||
return os.LengthProcessed(pvOutBuffer);
|
||||
}
|
||||
|
||||
27
vendor/stormlib-9/src/adpcm/adpcm.h
vendored
Normal file
27
vendor/stormlib-9/src/adpcm/adpcm.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*****************************************************************************/
|
||||
/* adpcm.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Header file for adpcm decompress functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 31.03.03 1.00 Lad The first version of adpcm.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __ADPCM_H__
|
||||
#define __ADPCM_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define MAX_ADPCM_CHANNEL_COUNT 2
|
||||
#define INITIAL_ADPCM_STEP_INDEX 0x2C
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
int CompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int nCmpType, int ChannelCount);
|
||||
int DecompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int ChannelCount);
|
||||
int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount);
|
||||
|
||||
#endif // __ADPCM_H__
|
||||
1094
vendor/stormlib-9/src/bzip2/blocksort.c
vendored
Normal file
1094
vendor/stormlib-9/src/bzip2/blocksort.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1573
vendor/stormlib-9/src/bzip2/bzlib.c
vendored
Normal file
1573
vendor/stormlib-9/src/bzip2/bzlib.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
282
vendor/stormlib-9/src/bzip2/bzlib.h
vendored
Normal file
282
vendor/stormlib-9/src/bzip2/bzlib.h
vendored
Normal file
@ -0,0 +1,282 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Public header file for the library. ---*/
|
||||
/*--- bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#ifndef _BZLIB_H
|
||||
#define _BZLIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BZ_RUN 0
|
||||
#define BZ_FLUSH 1
|
||||
#define BZ_FINISH 2
|
||||
|
||||
#define BZ_OK 0
|
||||
#define BZ_RUN_OK 1
|
||||
#define BZ_FLUSH_OK 2
|
||||
#define BZ_FINISH_OK 3
|
||||
#define BZ_STREAM_END 4
|
||||
#define BZ_SEQUENCE_ERROR (-1)
|
||||
#define BZ_PARAM_ERROR (-2)
|
||||
#define BZ_MEM_ERROR (-3)
|
||||
#define BZ_DATA_ERROR (-4)
|
||||
#define BZ_DATA_ERROR_MAGIC (-5)
|
||||
#define BZ_IO_ERROR (-6)
|
||||
#define BZ_UNEXPECTED_EOF (-7)
|
||||
#define BZ_OUTBUFF_FULL (-8)
|
||||
#define BZ_CONFIG_ERROR (-9)
|
||||
|
||||
typedef
|
||||
struct {
|
||||
char *next_in;
|
||||
unsigned int avail_in;
|
||||
unsigned int total_in_lo32;
|
||||
unsigned int total_in_hi32;
|
||||
|
||||
char *next_out;
|
||||
unsigned int avail_out;
|
||||
unsigned int total_out_lo32;
|
||||
unsigned int total_out_hi32;
|
||||
|
||||
void *state;
|
||||
|
||||
void *(*bzalloc)(void *,int,int);
|
||||
void (*bzfree)(void *,void *);
|
||||
void *opaque;
|
||||
}
|
||||
bz_stream;
|
||||
|
||||
|
||||
#ifndef BZ_IMPORT
|
||||
#define BZ_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
/* Need a definitition for FILE */
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# ifdef small
|
||||
/* windows.h define small to char */
|
||||
# undef small
|
||||
# endif
|
||||
# ifdef BZ_EXPORT
|
||||
# define BZ_API(func) WINAPI func
|
||||
# define BZ_EXTERN extern
|
||||
# else
|
||||
/* import windows dll dynamically */
|
||||
# define BZ_API(func) (WINAPI * func)
|
||||
# define BZ_EXTERN
|
||||
# endif
|
||||
#else
|
||||
# define BZ_API(func) func
|
||||
# define BZ_EXTERN extern
|
||||
#endif
|
||||
|
||||
|
||||
/*-- Core (low-level) library functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
|
||||
bz_stream* strm,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
|
||||
bz_stream* strm,
|
||||
int action
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
|
||||
bz_stream *strm,
|
||||
int verbosity,
|
||||
int small
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||
bz_stream *strm
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*-- High(er) level library functions --*/
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#define BZ_MAX_UNUSED 5000
|
||||
|
||||
typedef void BZFILE;
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int verbosity,
|
||||
int small,
|
||||
void* unused,
|
||||
int nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void** unused,
|
||||
int* nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzRead) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in,
|
||||
unsigned int* nbytes_out
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in_lo32,
|
||||
unsigned int* nbytes_in_hi32,
|
||||
unsigned int* nbytes_out_lo32,
|
||||
unsigned int* nbytes_out_hi32
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/*-- Utility functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int small,
|
||||
int verbosity
|
||||
);
|
||||
|
||||
|
||||
/*--
|
||||
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
|
||||
to support better zlib compatibility.
|
||||
This code is not _officially_ part of libbzip2 (yet);
|
||||
I haven't tested it, documented it, or considered the
|
||||
threading-safeness of it.
|
||||
If this code breaks, please contact both Yoshioka and me.
|
||||
--*/
|
||||
|
||||
BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
|
||||
void
|
||||
);
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
|
||||
const char *path,
|
||||
const char *mode
|
||||
);
|
||||
|
||||
BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
|
||||
int fd,
|
||||
const char *mode
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzread) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzflush) (
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzclose) (
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
|
||||
BZFILE *b,
|
||||
int *errnum
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
509
vendor/stormlib-9/src/bzip2/bzlib_private.h
vendored
Normal file
509
vendor/stormlib-9/src/bzip2/bzlib_private.h
vendored
Normal file
@ -0,0 +1,509 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Private header file for the library. ---*/
|
||||
/*--- bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#ifndef _BZLIB_PRIVATE_H
|
||||
#define _BZLIB_PRIVATE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "bzlib.h"
|
||||
|
||||
|
||||
|
||||
/*-- General stuff. --*/
|
||||
|
||||
#define BZ_VERSION "1.0.5, 10-Dec-2007"
|
||||
|
||||
typedef char Char;
|
||||
typedef unsigned char Bool;
|
||||
typedef unsigned char UChar;
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#define True ((Bool)1)
|
||||
#define False ((Bool)0)
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __inline__ /* */
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
|
||||
extern void BZ2_bz__AssertH__fail ( int errcode );
|
||||
#define AssertH(cond,errcode) \
|
||||
{ if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
|
||||
|
||||
#if BZ_DEBUG
|
||||
#define AssertD(cond,msg) \
|
||||
{ if (!(cond)) { \
|
||||
fprintf ( stderr, \
|
||||
"\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
|
||||
exit(1); \
|
||||
}}
|
||||
#else
|
||||
#define AssertD(cond,msg) /* */
|
||||
#endif
|
||||
|
||||
#define VPrintf0(zf) \
|
||||
fprintf(stderr,zf)
|
||||
#define VPrintf1(zf,za1) \
|
||||
fprintf(stderr,zf,za1)
|
||||
#define VPrintf2(zf,za1,za2) \
|
||||
fprintf(stderr,zf,za1,za2)
|
||||
#define VPrintf3(zf,za1,za2,za3) \
|
||||
fprintf(stderr,zf,za1,za2,za3)
|
||||
#define VPrintf4(zf,za1,za2,za3,za4) \
|
||||
fprintf(stderr,zf,za1,za2,za3,za4)
|
||||
#define VPrintf5(zf,za1,za2,za3,za4,za5) \
|
||||
fprintf(stderr,zf,za1,za2,za3,za4,za5)
|
||||
|
||||
#else
|
||||
|
||||
extern void bz_internal_error ( int errcode );
|
||||
#define AssertH(cond,errcode) \
|
||||
{ if (!(cond)) bz_internal_error ( errcode ); }
|
||||
#define AssertD(cond,msg) do { } while (0)
|
||||
#define VPrintf0(zf) do { } while (0)
|
||||
#define VPrintf1(zf,za1) do { } while (0)
|
||||
#define VPrintf2(zf,za1,za2) do { } while (0)
|
||||
#define VPrintf3(zf,za1,za2,za3) do { } while (0)
|
||||
#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0)
|
||||
#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
|
||||
#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
|
||||
|
||||
|
||||
/*-- Header bytes. --*/
|
||||
|
||||
#define BZ_HDR_B 0x42 /* 'B' */
|
||||
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||
#define BZ_HDR_h 0x68 /* 'h' */
|
||||
#define BZ_HDR_0 0x30 /* '0' */
|
||||
|
||||
/*-- Constants for the back end. --*/
|
||||
|
||||
#define BZ_MAX_ALPHA_SIZE 258
|
||||
#define BZ_MAX_CODE_LEN 23
|
||||
|
||||
#define BZ_RUNA 0
|
||||
#define BZ_RUNB 1
|
||||
|
||||
#define BZ_N_GROUPS 6
|
||||
#define BZ_G_SIZE 50
|
||||
#define BZ_N_ITERS 4
|
||||
|
||||
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
|
||||
|
||||
|
||||
|
||||
/*-- Stuff for randomising repetitive blocks. --*/
|
||||
|
||||
extern Int32 BZ2_rNums[512];
|
||||
|
||||
#define BZ_RAND_DECLS \
|
||||
Int32 rNToGo; \
|
||||
Int32 rTPos \
|
||||
|
||||
#define BZ_RAND_INIT_MASK \
|
||||
s->rNToGo = 0; \
|
||||
s->rTPos = 0 \
|
||||
|
||||
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
|
||||
|
||||
#define BZ_RAND_UPD_MASK \
|
||||
if (s->rNToGo == 0) { \
|
||||
s->rNToGo = BZ2_rNums[s->rTPos]; \
|
||||
s->rTPos++; \
|
||||
if (s->rTPos == 512) s->rTPos = 0; \
|
||||
} \
|
||||
s->rNToGo--;
|
||||
|
||||
|
||||
|
||||
/*-- Stuff for doing CRCs. --*/
|
||||
|
||||
extern UInt32 BZ2_crc32Table[256];
|
||||
|
||||
#define BZ_INITIALISE_CRC(crcVar) \
|
||||
{ \
|
||||
crcVar = 0xffffffffL; \
|
||||
}
|
||||
|
||||
#define BZ_FINALISE_CRC(crcVar) \
|
||||
{ \
|
||||
crcVar = ~(crcVar); \
|
||||
}
|
||||
|
||||
#define BZ_UPDATE_CRC(crcVar,cha) \
|
||||
{ \
|
||||
crcVar = (crcVar << 8) ^ \
|
||||
BZ2_crc32Table[(crcVar >> 24) ^ \
|
||||
((UChar)cha)]; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-- States and modes for compression. --*/
|
||||
|
||||
#define BZ_M_IDLE 1
|
||||
#define BZ_M_RUNNING 2
|
||||
#define BZ_M_FLUSHING 3
|
||||
#define BZ_M_FINISHING 4
|
||||
|
||||
#define BZ_S_OUTPUT 1
|
||||
#define BZ_S_INPUT 2
|
||||
|
||||
#define BZ_N_RADIX 2
|
||||
#define BZ_N_QSORT 12
|
||||
#define BZ_N_SHELL 18
|
||||
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
|
||||
|
||||
|
||||
|
||||
|
||||
/*-- Structure holding all the compression-side stuff. --*/
|
||||
|
||||
typedef
|
||||
struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* mode this stream is in, and whether inputting */
|
||||
/* or outputting data */
|
||||
Int32 mode;
|
||||
Int32 state;
|
||||
|
||||
/* remembers avail_in when flush/finish requested */
|
||||
UInt32 avail_in_expect;
|
||||
|
||||
/* for doing the block sorting */
|
||||
UInt32* arr1;
|
||||
UInt32* arr2;
|
||||
UInt32* ftab;
|
||||
Int32 origPtr;
|
||||
|
||||
/* aliases for arr1 and arr2 */
|
||||
UInt32* ptr;
|
||||
UChar* block;
|
||||
UInt16* mtfv;
|
||||
UChar* zbits;
|
||||
|
||||
/* for deciding when to use the fallback sorting algorithm */
|
||||
Int32 workFactor;
|
||||
|
||||
/* run-length-encoding of the input */
|
||||
UInt32 state_in_ch;
|
||||
Int32 state_in_len;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* input and output limits and current posns */
|
||||
Int32 nblock;
|
||||
Int32 nblockMAX;
|
||||
Int32 numZ;
|
||||
Int32 state_out_pos;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
UChar unseqToSeq[256];
|
||||
|
||||
/* the buffer for bit stream creation */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* block and combined CRCs */
|
||||
UInt32 blockCRC;
|
||||
UInt32 combinedCRC;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 verbosity;
|
||||
Int32 blockNo;
|
||||
Int32 blockSize100k;
|
||||
|
||||
/* stuff for coding the MTF values */
|
||||
Int32 nMTF;
|
||||
Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
|
||||
UChar selector [BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
/* second dimension: only 3 needed; 4 makes index calculations faster */
|
||||
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
|
||||
|
||||
}
|
||||
EState;
|
||||
|
||||
|
||||
|
||||
/*-- externs for compression. --*/
|
||||
|
||||
extern void
|
||||
BZ2_blockSort ( EState* );
|
||||
|
||||
extern void
|
||||
BZ2_compressBlock ( EState*, Bool );
|
||||
|
||||
extern void
|
||||
BZ2_bsInitWrite ( EState* );
|
||||
|
||||
extern void
|
||||
BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
|
||||
|
||||
extern void
|
||||
BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
|
||||
|
||||
|
||||
|
||||
/*-- states for decompression. --*/
|
||||
|
||||
#define BZ_X_IDLE 1
|
||||
#define BZ_X_OUTPUT 2
|
||||
|
||||
#define BZ_X_MAGIC_1 10
|
||||
#define BZ_X_MAGIC_2 11
|
||||
#define BZ_X_MAGIC_3 12
|
||||
#define BZ_X_MAGIC_4 13
|
||||
#define BZ_X_BLKHDR_1 14
|
||||
#define BZ_X_BLKHDR_2 15
|
||||
#define BZ_X_BLKHDR_3 16
|
||||
#define BZ_X_BLKHDR_4 17
|
||||
#define BZ_X_BLKHDR_5 18
|
||||
#define BZ_X_BLKHDR_6 19
|
||||
#define BZ_X_BCRC_1 20
|
||||
#define BZ_X_BCRC_2 21
|
||||
#define BZ_X_BCRC_3 22
|
||||
#define BZ_X_BCRC_4 23
|
||||
#define BZ_X_RANDBIT 24
|
||||
#define BZ_X_ORIGPTR_1 25
|
||||
#define BZ_X_ORIGPTR_2 26
|
||||
#define BZ_X_ORIGPTR_3 27
|
||||
#define BZ_X_MAPPING_1 28
|
||||
#define BZ_X_MAPPING_2 29
|
||||
#define BZ_X_SELECTOR_1 30
|
||||
#define BZ_X_SELECTOR_2 31
|
||||
#define BZ_X_SELECTOR_3 32
|
||||
#define BZ_X_CODING_1 33
|
||||
#define BZ_X_CODING_2 34
|
||||
#define BZ_X_CODING_3 35
|
||||
#define BZ_X_MTF_1 36
|
||||
#define BZ_X_MTF_2 37
|
||||
#define BZ_X_MTF_3 38
|
||||
#define BZ_X_MTF_4 39
|
||||
#define BZ_X_MTF_5 40
|
||||
#define BZ_X_MTF_6 41
|
||||
#define BZ_X_ENDHDR_2 42
|
||||
#define BZ_X_ENDHDR_3 43
|
||||
#define BZ_X_ENDHDR_4 44
|
||||
#define BZ_X_ENDHDR_5 45
|
||||
#define BZ_X_ENDHDR_6 46
|
||||
#define BZ_X_CCRC_1 47
|
||||
#define BZ_X_CCRC_2 48
|
||||
#define BZ_X_CCRC_3 49
|
||||
#define BZ_X_CCRC_4 50
|
||||
|
||||
|
||||
|
||||
/*-- Constants for the fast MTF decoder. --*/
|
||||
|
||||
#define MTFA_SIZE 4096
|
||||
#define MTFL_SIZE 16
|
||||
|
||||
|
||||
|
||||
/*-- Structure holding all the decompression-side stuff. --*/
|
||||
|
||||
typedef
|
||||
struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* state indicator for this stream */
|
||||
Int32 state;
|
||||
|
||||
/* for doing the final run-length decoding */
|
||||
UChar state_out_ch;
|
||||
Int32 state_out_len;
|
||||
Bool blockRandomised;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* the buffer for bit stream reading */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 blockSize100k;
|
||||
Bool smallDecompress;
|
||||
Int32 currBlockNo;
|
||||
Int32 verbosity;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform */
|
||||
Int32 origPtr;
|
||||
UInt32 tPos;
|
||||
Int32 k0;
|
||||
Int32 unzftab[256];
|
||||
Int32 nblock_used;
|
||||
Int32 cftab[257];
|
||||
Int32 cftabCopy[257];
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (FAST) */
|
||||
UInt32 *tt;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (SMALL) */
|
||||
UInt16 *ll16;
|
||||
UChar *ll4;
|
||||
|
||||
/* stored and calculated CRCs */
|
||||
UInt32 storedBlockCRC;
|
||||
UInt32 storedCombinedCRC;
|
||||
UInt32 calculatedBlockCRC;
|
||||
UInt32 calculatedCombinedCRC;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
Bool inUse16[16];
|
||||
UChar seqToUnseq[256];
|
||||
|
||||
/* for decoding the MTF values */
|
||||
UChar mtfa [MTFA_SIZE];
|
||||
Int32 mtfbase[256 / MTFL_SIZE];
|
||||
UChar selector [BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
|
||||
Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 minLens[BZ_N_GROUPS];
|
||||
|
||||
/* save area for scalars in the main decompress code */
|
||||
Int32 save_i;
|
||||
Int32 save_j;
|
||||
Int32 save_t;
|
||||
Int32 save_alphaSize;
|
||||
Int32 save_nGroups;
|
||||
Int32 save_nSelectors;
|
||||
Int32 save_EOB;
|
||||
Int32 save_groupNo;
|
||||
Int32 save_groupPos;
|
||||
Int32 save_nextSym;
|
||||
Int32 save_nblockMAX;
|
||||
Int32 save_nblock;
|
||||
Int32 save_es;
|
||||
Int32 save_N;
|
||||
Int32 save_curr;
|
||||
Int32 save_zt;
|
||||
Int32 save_zn;
|
||||
Int32 save_zvec;
|
||||
Int32 save_zj;
|
||||
Int32 save_gSel;
|
||||
Int32 save_gMinlen;
|
||||
Int32* save_gLimit;
|
||||
Int32* save_gBase;
|
||||
Int32* save_gPerm;
|
||||
|
||||
}
|
||||
DState;
|
||||
|
||||
|
||||
|
||||
/*-- Macros for decompression. --*/
|
||||
|
||||
#define BZ_GET_FAST(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
|
||||
s->tPos = s->tt[s->tPos]; \
|
||||
cccc = (UChar)(s->tPos & 0xff); \
|
||||
s->tPos >>= 8;
|
||||
|
||||
#define BZ_GET_FAST_C(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \
|
||||
c_tPos = c_tt[c_tPos]; \
|
||||
cccc = (UChar)(c_tPos & 0xff); \
|
||||
c_tPos >>= 8;
|
||||
|
||||
#define SET_LL4(i,n) \
|
||||
{ if (((i) & 0x1) == 0) \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
|
||||
}
|
||||
|
||||
#define GET_LL4(i) \
|
||||
((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
|
||||
|
||||
#define SET_LL(i,n) \
|
||||
{ s->ll16[i] = (UInt16)(n & 0x0000ffff); \
|
||||
SET_LL4(i, n >> 16); \
|
||||
}
|
||||
|
||||
#define GET_LL(i) \
|
||||
(((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
|
||||
|
||||
#define BZ_GET_SMALL(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
|
||||
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
|
||||
s->tPos = GET_LL(s->tPos);
|
||||
|
||||
|
||||
/*-- externs for decompression. --*/
|
||||
|
||||
extern Int32
|
||||
BZ2_indexIntoF ( Int32, Int32* );
|
||||
|
||||
extern Int32
|
||||
BZ2_decompress ( DState* );
|
||||
|
||||
extern void
|
||||
BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
|
||||
Int32, Int32, Int32 );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
|
||||
|
||||
#ifdef BZ_NO_STDIO
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
672
vendor/stormlib-9/src/bzip2/compress.c
vendored
Normal file
672
vendor/stormlib-9/src/bzip2/compress.c
vendored
Normal file
@ -0,0 +1,672 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Compression machinery (not incl block sorting) ---*/
|
||||
/*--- compress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* CHANGES
|
||||
0.9.0 -- original version.
|
||||
0.9.0a/b -- no changes in this file.
|
||||
0.9.0c -- changed setting of nGroups in sendMTFValues()
|
||||
so as to do a bit better on small files
|
||||
*/
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- Bit stream I/O ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_bsInitWrite ( EState* s )
|
||||
{
|
||||
s->bsLive = 0;
|
||||
s->bsBuff = 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsFinishWrite ( EState* s )
|
||||
{
|
||||
while (s->bsLive > 0) {
|
||||
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
|
||||
s->numZ++;
|
||||
s->bsBuff <<= 8;
|
||||
s->bsLive -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define bsNEEDW(nz) \
|
||||
{ \
|
||||
while (s->bsLive >= 8) { \
|
||||
s->zbits[s->numZ] \
|
||||
= (UChar)(s->bsBuff >> 24); \
|
||||
s->numZ++; \
|
||||
s->bsBuff <<= 8; \
|
||||
s->bsLive -= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
__inline__
|
||||
void bsW ( EState* s, Int32 n, UInt32 v )
|
||||
{
|
||||
bsNEEDW ( n );
|
||||
s->bsBuff |= (v << (32 - s->bsLive - n));
|
||||
s->bsLive += n;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsPutUInt32 ( EState* s, UInt32 u )
|
||||
{
|
||||
bsW ( s, 8, (u >> 24) & 0xffL );
|
||||
bsW ( s, 8, (u >> 16) & 0xffL );
|
||||
bsW ( s, 8, (u >> 8) & 0xffL );
|
||||
bsW ( s, 8, u & 0xffL );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsPutUChar ( EState* s, UChar c )
|
||||
{
|
||||
bsW( s, 8, (UInt32)c );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- The back end proper ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void makeMaps_e ( EState* s )
|
||||
{
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->unseqToSeq[i] = s->nInUse;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void generateMTFValues ( EState* s )
|
||||
{
|
||||
UChar yy[256];
|
||||
Int32 i, j;
|
||||
Int32 zPend;
|
||||
Int32 wr;
|
||||
Int32 EOB;
|
||||
|
||||
/*
|
||||
After sorting (eg, here),
|
||||
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
|
||||
and
|
||||
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
|
||||
holds the original block data.
|
||||
|
||||
The first thing to do is generate the MTF values,
|
||||
and put them in
|
||||
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
|
||||
Because there are strictly fewer or equal MTF values
|
||||
than block values, ptr values in this area are overwritten
|
||||
with MTF values only when they are no longer needed.
|
||||
|
||||
The final compressed bitstream is generated into the
|
||||
area starting at
|
||||
(UChar*) (&((UChar*)s->arr2)[s->nblock])
|
||||
|
||||
These storage aliases are set up in bzCompressInit(),
|
||||
except for the last one, which is arranged in
|
||||
compressBlock().
|
||||
*/
|
||||
UInt32* ptr = s->ptr;
|
||||
UChar* block = s->block;
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
makeMaps_e ( s );
|
||||
EOB = s->nInUse+1;
|
||||
|
||||
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
|
||||
|
||||
wr = 0;
|
||||
zPend = 0;
|
||||
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
|
||||
|
||||
for (i = 0; i < s->nblock; i++) {
|
||||
UChar ll_i;
|
||||
AssertD ( wr <= i, "generateMTFValues(1)" );
|
||||
j = ptr[i]-1; if (j < 0) j += s->nblock;
|
||||
ll_i = s->unseqToSeq[block[j]];
|
||||
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
|
||||
|
||||
if (yy[0] == ll_i) {
|
||||
zPend++;
|
||||
} else {
|
||||
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB; wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
} else {
|
||||
mtfv[wr] = BZ_RUNA; wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2) break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
{
|
||||
register UChar rtmp;
|
||||
register UChar* ryy_j;
|
||||
register UChar rll_i;
|
||||
rtmp = yy[1];
|
||||
yy[1] = yy[0];
|
||||
ryy_j = &(yy[1]);
|
||||
rll_i = ll_i;
|
||||
while ( rll_i != rtmp ) {
|
||||
register UChar rtmp2;
|
||||
ryy_j++;
|
||||
rtmp2 = rtmp;
|
||||
rtmp = *ryy_j;
|
||||
*ryy_j = rtmp2;
|
||||
};
|
||||
yy[0] = rtmp;
|
||||
j = ryy_j - &(yy[0]);
|
||||
mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB; wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
} else {
|
||||
mtfv[wr] = BZ_RUNA; wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2) break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
|
||||
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
|
||||
|
||||
s->nMTF = wr;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define BZ_LESSER_ICOST 0
|
||||
#define BZ_GREATER_ICOST 15
|
||||
|
||||
static
|
||||
void sendMTFValues ( EState* s )
|
||||
{
|
||||
Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
|
||||
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
|
||||
Int32 nGroups, nBytes;
|
||||
|
||||
/*--
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
is a global since the decoder also needs it.
|
||||
|
||||
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
are also globals only used in this proc.
|
||||
Made global to keep stack frame size small.
|
||||
--*/
|
||||
|
||||
|
||||
UInt16 cost[BZ_N_GROUPS];
|
||||
Int32 fave[BZ_N_GROUPS];
|
||||
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
|
||||
"%d+2 syms in use\n",
|
||||
s->nblock, s->nMTF, s->nInUse );
|
||||
|
||||
alphaSize = s->nInUse+2;
|
||||
for (t = 0; t < BZ_N_GROUPS; t++)
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
s->len[t][v] = BZ_GREATER_ICOST;
|
||||
|
||||
/*--- Decide how many coding tables to use ---*/
|
||||
AssertH ( s->nMTF > 0, 3001 );
|
||||
if (s->nMTF < 200) nGroups = 2; else
|
||||
if (s->nMTF < 600) nGroups = 3; else
|
||||
if (s->nMTF < 1200) nGroups = 4; else
|
||||
if (s->nMTF < 2400) nGroups = 5; else
|
||||
nGroups = 6;
|
||||
|
||||
/*--- Generate an initial set of coding tables ---*/
|
||||
{
|
||||
Int32 nPart, remF, tFreq, aFreq;
|
||||
|
||||
nPart = nGroups;
|
||||
remF = s->nMTF;
|
||||
gs = 0;
|
||||
while (nPart > 0) {
|
||||
tFreq = remF / nPart;
|
||||
ge = gs-1;
|
||||
aFreq = 0;
|
||||
while (aFreq < tFreq && ge < alphaSize-1) {
|
||||
ge++;
|
||||
aFreq += s->mtfFreq[ge];
|
||||
}
|
||||
|
||||
if (ge > gs
|
||||
&& nPart != nGroups && nPart != 1
|
||||
&& ((nGroups-nPart) % 2 == 1)) {
|
||||
aFreq -= s->mtfFreq[ge];
|
||||
ge--;
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf5( " initial group %d, [%d .. %d], "
|
||||
"has %d syms (%4.1f%%)\n",
|
||||
nPart, gs, ge, aFreq,
|
||||
(100.0 * (float)aFreq) / (float)(s->nMTF) );
|
||||
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
if (v >= gs && v <= ge)
|
||||
s->len[nPart-1][v] = BZ_LESSER_ICOST; else
|
||||
s->len[nPart-1][v] = BZ_GREATER_ICOST;
|
||||
|
||||
nPart--;
|
||||
gs = ge+1;
|
||||
remF -= aFreq;
|
||||
}
|
||||
}
|
||||
|
||||
/*---
|
||||
Iterate up to BZ_N_ITERS times to improve the tables.
|
||||
---*/
|
||||
for (iter = 0; iter < BZ_N_ITERS; iter++) {
|
||||
|
||||
for (t = 0; t < nGroups; t++) fave[t] = 0;
|
||||
|
||||
for (t = 0; t < nGroups; t++)
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
s->rfreq[t][v] = 0;
|
||||
|
||||
/*---
|
||||
Set up an auxiliary length table which is used to fast-track
|
||||
the common case (nGroups == 6).
|
||||
---*/
|
||||
if (nGroups == 6) {
|
||||
for (v = 0; v < alphaSize; v++) {
|
||||
s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
|
||||
s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
|
||||
s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
|
||||
}
|
||||
}
|
||||
|
||||
nSelectors = 0;
|
||||
totc = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
|
||||
/*--- Set group start & end marks. --*/
|
||||
if (gs >= s->nMTF) break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||
|
||||
/*--
|
||||
Calculate the cost of this group as coded
|
||||
by each of the coding tables.
|
||||
--*/
|
||||
for (t = 0; t < nGroups; t++) cost[t] = 0;
|
||||
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
register UInt32 cost01, cost23, cost45;
|
||||
register UInt16 icv;
|
||||
cost01 = cost23 = cost45 = 0;
|
||||
|
||||
# define BZ_ITER(nn) \
|
||||
icv = mtfv[gs+(nn)]; \
|
||||
cost01 += s->len_pack[icv][0]; \
|
||||
cost23 += s->len_pack[icv][1]; \
|
||||
cost45 += s->len_pack[icv][2]; \
|
||||
|
||||
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
|
||||
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
|
||||
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
|
||||
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
|
||||
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
|
||||
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
|
||||
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
|
||||
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
|
||||
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
|
||||
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
|
||||
|
||||
# undef BZ_ITER
|
||||
|
||||
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
|
||||
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
|
||||
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
UInt16 icv = mtfv[i];
|
||||
for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
|
||||
}
|
||||
}
|
||||
|
||||
/*--
|
||||
Find the coding table which is best for this group,
|
||||
and record its identity in the selector table.
|
||||
--*/
|
||||
bc = 999999999; bt = -1;
|
||||
for (t = 0; t < nGroups; t++)
|
||||
if (cost[t] < bc) { bc = cost[t]; bt = t; };
|
||||
totc += bc;
|
||||
fave[bt]++;
|
||||
s->selector[nSelectors] = bt;
|
||||
nSelectors++;
|
||||
|
||||
/*--
|
||||
Increment the symbol frequencies for the selected table.
|
||||
--*/
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
|
||||
# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
|
||||
|
||||
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
|
||||
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
|
||||
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
|
||||
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
|
||||
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
|
||||
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
|
||||
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
|
||||
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
|
||||
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
|
||||
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
|
||||
|
||||
# undef BZ_ITUR
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++)
|
||||
s->rfreq[bt][ mtfv[i] ]++;
|
||||
}
|
||||
|
||||
gs = ge+1;
|
||||
}
|
||||
if (s->verbosity >= 3) {
|
||||
VPrintf2 ( " pass %d: size is %d, grp uses are ",
|
||||
iter+1, totc/8 );
|
||||
for (t = 0; t < nGroups; t++)
|
||||
VPrintf1 ( "%d ", fave[t] );
|
||||
VPrintf0 ( "\n" );
|
||||
}
|
||||
|
||||
/*--
|
||||
Recompute the tables based on the accumulated frequencies.
|
||||
--*/
|
||||
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
|
||||
comment in huffman.c for details. */
|
||||
for (t = 0; t < nGroups; t++)
|
||||
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
|
||||
alphaSize, 17 /*20*/ );
|
||||
}
|
||||
|
||||
|
||||
AssertH( nGroups < 8, 3002 );
|
||||
AssertH( nSelectors < 32768 &&
|
||||
nSelectors <= (2 + (900000 / BZ_G_SIZE)),
|
||||
3003 );
|
||||
|
||||
|
||||
/*--- Compute MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
|
||||
for (i = 0; i < nGroups; i++) pos[i] = i;
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
ll_i = s->selector[i];
|
||||
j = 0;
|
||||
tmp = pos[j];
|
||||
while ( ll_i != tmp ) {
|
||||
j++;
|
||||
tmp2 = tmp;
|
||||
tmp = pos[j];
|
||||
pos[j] = tmp2;
|
||||
};
|
||||
pos[0] = tmp;
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
};
|
||||
|
||||
/*--- Assign actual codes for the tables. --*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||
}
|
||||
AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
|
||||
AssertH ( !(minLen < 1), 3005 );
|
||||
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
|
||||
minLen, maxLen, alphaSize );
|
||||
}
|
||||
|
||||
/*--- Transmit the mapping table. ---*/
|
||||
{
|
||||
Bool inUse16[16];
|
||||
for (i = 0; i < 16; i++) {
|
||||
inUse16[i] = False;
|
||||
for (j = 0; j < 16; j++)
|
||||
if (s->inUse[i * 16 + j]) inUse16[i] = True;
|
||||
}
|
||||
|
||||
nBytes = s->numZ;
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
|
||||
}
|
||||
|
||||
/*--- Now the selectors. ---*/
|
||||
nBytes = s->numZ;
|
||||
bsW ( s, 3, nGroups );
|
||||
bsW ( s, 15, nSelectors );
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
|
||||
bsW(s,1,0);
|
||||
}
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( "selectors %d, ", s->numZ-nBytes );
|
||||
|
||||
/*--- Now the coding tables. ---*/
|
||||
nBytes = s->numZ;
|
||||
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
Int32 curr = s->len[t][0];
|
||||
bsW ( s, 5, curr );
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
|
||||
while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
|
||||
bsW ( s, 1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
|
||||
|
||||
/*--- And finally, the block data proper ---*/
|
||||
nBytes = s->numZ;
|
||||
selCtr = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
if (gs >= s->nMTF) break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||
AssertH ( s->selector[selCtr] < nGroups, 3006 );
|
||||
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
UInt16 mtfv_i;
|
||||
UChar* s_len_sel_selCtr
|
||||
= &(s->len[s->selector[selCtr]][0]);
|
||||
Int32* s_code_sel_selCtr
|
||||
= &(s->code[s->selector[selCtr]][0]);
|
||||
|
||||
# define BZ_ITAH(nn) \
|
||||
mtfv_i = mtfv[gs+(nn)]; \
|
||||
bsW ( s, \
|
||||
s_len_sel_selCtr[mtfv_i], \
|
||||
s_code_sel_selCtr[mtfv_i] )
|
||||
|
||||
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
|
||||
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
|
||||
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
|
||||
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
|
||||
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
|
||||
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
|
||||
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
|
||||
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
|
||||
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
|
||||
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
|
||||
|
||||
# undef BZ_ITAH
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
bsW ( s,
|
||||
s->len [s->selector[selCtr]] [mtfv[i]],
|
||||
s->code [s->selector[selCtr]] [mtfv[i]] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gs = ge+1;
|
||||
selCtr++;
|
||||
}
|
||||
AssertH( selCtr == nSelectors, 3007 );
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( "codes %d\n", s->numZ-nBytes );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_compressBlock ( EState* s, Bool is_last_block )
|
||||
{
|
||||
if (s->nblock > 0) {
|
||||
|
||||
BZ_FINALISE_CRC ( s->blockCRC );
|
||||
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
|
||||
s->combinedCRC ^= s->blockCRC;
|
||||
if (s->blockNo > 1) s->numZ = 0;
|
||||
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf4( " block %d: crc = 0x%08x, "
|
||||
"combined CRC = 0x%08x, size = %d\n",
|
||||
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
|
||||
|
||||
BZ2_blockSort ( s );
|
||||
}
|
||||
|
||||
s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
|
||||
|
||||
/*-- If this is the first block, create the stream header. --*/
|
||||
if (s->blockNo == 1) {
|
||||
BZ2_bsInitWrite ( s );
|
||||
bsPutUChar ( s, BZ_HDR_B );
|
||||
bsPutUChar ( s, BZ_HDR_Z );
|
||||
bsPutUChar ( s, BZ_HDR_h );
|
||||
bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
|
||||
}
|
||||
|
||||
if (s->nblock > 0) {
|
||||
|
||||
bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
|
||||
bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
|
||||
bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
|
||||
|
||||
/*-- Now the block's CRC, so it is in a known place. --*/
|
||||
bsPutUInt32 ( s, s->blockCRC );
|
||||
|
||||
/*--
|
||||
Now a single bit indicating (non-)randomisation.
|
||||
As of version 0.9.5, we use a better sorting algorithm
|
||||
which makes randomisation unnecessary. So always set
|
||||
the randomised bit to 'no'. Of course, the decoder
|
||||
still needs to be able to handle randomised blocks
|
||||
so as to maintain backwards compatibility with
|
||||
older versions of bzip2.
|
||||
--*/
|
||||
bsW(s,1,0);
|
||||
|
||||
bsW ( s, 24, s->origPtr );
|
||||
generateMTFValues ( s );
|
||||
sendMTFValues ( s );
|
||||
}
|
||||
|
||||
|
||||
/*-- If this is the last block, add the stream trailer. --*/
|
||||
if (is_last_block) {
|
||||
|
||||
bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
|
||||
bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
|
||||
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
|
||||
bsPutUInt32 ( s, s->combinedCRC );
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
|
||||
bsFinishWrite ( s );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end compress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
104
vendor/stormlib-9/src/bzip2/crctable.c
vendored
Normal file
104
vendor/stormlib-9/src/bzip2/crctable.c
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for doing CRCs ---*/
|
||||
/*--- crctable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
/*--
|
||||
I think this is an implementation of the AUTODIN-II,
|
||||
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
|
||||
from code by Rob Warnock, in Section 51 of the
|
||||
comp.compression FAQ.
|
||||
--*/
|
||||
|
||||
UInt32 BZ2_crc32Table[256] = {
|
||||
|
||||
/*-- Ugly, innit? --*/
|
||||
|
||||
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
|
||||
0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
|
||||
0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
|
||||
0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
|
||||
0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
|
||||
0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
|
||||
0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
|
||||
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
|
||||
0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
|
||||
0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
|
||||
0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
|
||||
0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
|
||||
0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
|
||||
0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
|
||||
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
|
||||
0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
|
||||
0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
|
||||
0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
|
||||
0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
|
||||
0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
|
||||
0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
|
||||
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
|
||||
0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
|
||||
0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
|
||||
0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
|
||||
0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
|
||||
0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
|
||||
0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
|
||||
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
|
||||
0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
|
||||
0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
|
||||
0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
|
||||
0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
|
||||
0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
|
||||
0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
|
||||
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
|
||||
0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
|
||||
0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
|
||||
0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
|
||||
0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
|
||||
0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
|
||||
0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
|
||||
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
|
||||
0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
|
||||
0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
|
||||
0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
|
||||
0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
|
||||
0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
|
||||
0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
|
||||
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
|
||||
0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
|
||||
0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
|
||||
0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
|
||||
0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
|
||||
0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
|
||||
0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
|
||||
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
|
||||
0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
|
||||
0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
|
||||
0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
|
||||
0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
|
||||
0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
|
||||
0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
|
||||
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end crctable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
626
vendor/stormlib-9/src/bzip2/decompress.c
vendored
Normal file
626
vendor/stormlib-9/src/bzip2/decompress.c
vendored
Normal file
@ -0,0 +1,626 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Decompression machinery ---*/
|
||||
/*--- decompress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void makeMaps_d ( DState* s )
|
||||
{
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->seqToUnseq[s->nInUse] = i;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define RETURN(rrr) \
|
||||
{ retVal = rrr; goto save_state_and_return; };
|
||||
|
||||
#define GET_BITS(lll,vvv,nnn) \
|
||||
case lll: s->state = lll; \
|
||||
while (True) { \
|
||||
if (s->bsLive >= nnn) { \
|
||||
UInt32 v; \
|
||||
v = (s->bsBuff >> \
|
||||
(s->bsLive-nnn)) & ((1 << nnn)-1); \
|
||||
s->bsLive -= nnn; \
|
||||
vvv = v; \
|
||||
break; \
|
||||
} \
|
||||
if (s->strm->avail_in == 0) RETURN(BZ_OK); \
|
||||
s->bsBuff \
|
||||
= (s->bsBuff << 8) | \
|
||||
((UInt32) \
|
||||
(*((UChar*)(s->strm->next_in)))); \
|
||||
s->bsLive += 8; \
|
||||
s->strm->next_in++; \
|
||||
s->strm->avail_in--; \
|
||||
s->strm->total_in_lo32++; \
|
||||
if (s->strm->total_in_lo32 == 0) \
|
||||
s->strm->total_in_hi32++; \
|
||||
}
|
||||
|
||||
#define GET_UCHAR(lll,uuu) \
|
||||
GET_BITS(lll,uuu,8)
|
||||
|
||||
#define GET_BIT(lll,uuu) \
|
||||
GET_BITS(lll,uuu,1)
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define GET_MTF_VAL(label1,label2,lval) \
|
||||
{ \
|
||||
if (groupPos == 0) { \
|
||||
groupNo++; \
|
||||
if (groupNo >= nSelectors) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
groupPos = BZ_G_SIZE; \
|
||||
gSel = s->selector[groupNo]; \
|
||||
gMinlen = s->minLens[gSel]; \
|
||||
gLimit = &(s->limit[gSel][0]); \
|
||||
gPerm = &(s->perm[gSel][0]); \
|
||||
gBase = &(s->base[gSel][0]); \
|
||||
} \
|
||||
groupPos--; \
|
||||
zn = gMinlen; \
|
||||
GET_BITS(label1, zvec, zn); \
|
||||
while (1) { \
|
||||
if (zn > 20 /* the longest code */) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
if (zvec <= gLimit[zn]) break; \
|
||||
zn++; \
|
||||
GET_BIT(label2, zj); \
|
||||
zvec = (zvec << 1) | zj; \
|
||||
}; \
|
||||
if (zvec - gBase[zn] < 0 \
|
||||
|| zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
lval = gPerm[zvec - gBase[zn]]; \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
Int32 BZ2_decompress ( DState* s )
|
||||
{
|
||||
UChar uc;
|
||||
Int32 retVal;
|
||||
Int32 minLen, maxLen;
|
||||
bz_stream* strm = s->strm;
|
||||
|
||||
/* stuff that needs to be saved/restored */
|
||||
Int32 i;
|
||||
Int32 j;
|
||||
Int32 t;
|
||||
Int32 alphaSize;
|
||||
Int32 nGroups;
|
||||
Int32 nSelectors;
|
||||
Int32 EOB;
|
||||
Int32 groupNo;
|
||||
Int32 groupPos;
|
||||
Int32 nextSym;
|
||||
Int32 nblockMAX;
|
||||
Int32 nblock;
|
||||
Int32 es;
|
||||
Int32 N;
|
||||
Int32 curr;
|
||||
Int32 zt;
|
||||
Int32 zn;
|
||||
Int32 zvec;
|
||||
Int32 zj;
|
||||
Int32 gSel;
|
||||
Int32 gMinlen;
|
||||
Int32* gLimit;
|
||||
Int32* gBase;
|
||||
Int32* gPerm;
|
||||
|
||||
if (s->state == BZ_X_MAGIC_1) {
|
||||
/*initialise the save area*/
|
||||
s->save_i = 0;
|
||||
s->save_j = 0;
|
||||
s->save_t = 0;
|
||||
s->save_alphaSize = 0;
|
||||
s->save_nGroups = 0;
|
||||
s->save_nSelectors = 0;
|
||||
s->save_EOB = 0;
|
||||
s->save_groupNo = 0;
|
||||
s->save_groupPos = 0;
|
||||
s->save_nextSym = 0;
|
||||
s->save_nblockMAX = 0;
|
||||
s->save_nblock = 0;
|
||||
s->save_es = 0;
|
||||
s->save_N = 0;
|
||||
s->save_curr = 0;
|
||||
s->save_zt = 0;
|
||||
s->save_zn = 0;
|
||||
s->save_zvec = 0;
|
||||
s->save_zj = 0;
|
||||
s->save_gSel = 0;
|
||||
s->save_gMinlen = 0;
|
||||
s->save_gLimit = NULL;
|
||||
s->save_gBase = NULL;
|
||||
s->save_gPerm = NULL;
|
||||
}
|
||||
|
||||
/*restore from the save area*/
|
||||
i = s->save_i;
|
||||
j = s->save_j;
|
||||
t = s->save_t;
|
||||
alphaSize = s->save_alphaSize;
|
||||
nGroups = s->save_nGroups;
|
||||
nSelectors = s->save_nSelectors;
|
||||
EOB = s->save_EOB;
|
||||
groupNo = s->save_groupNo;
|
||||
groupPos = s->save_groupPos;
|
||||
nextSym = s->save_nextSym;
|
||||
nblockMAX = s->save_nblockMAX;
|
||||
nblock = s->save_nblock;
|
||||
es = s->save_es;
|
||||
N = s->save_N;
|
||||
curr = s->save_curr;
|
||||
zt = s->save_zt;
|
||||
zn = s->save_zn;
|
||||
zvec = s->save_zvec;
|
||||
zj = s->save_zj;
|
||||
gSel = s->save_gSel;
|
||||
gMinlen = s->save_gMinlen;
|
||||
gLimit = s->save_gLimit;
|
||||
gBase = s->save_gBase;
|
||||
gPerm = s->save_gPerm;
|
||||
|
||||
retVal = BZ_OK;
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_1, uc);
|
||||
if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_2, uc);
|
||||
if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_3, uc)
|
||||
if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
|
||||
if (s->blockSize100k < (BZ_HDR_0 + 1) ||
|
||||
s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
s->blockSize100k -= BZ_HDR_0;
|
||||
|
||||
if (s->smallDecompress) {
|
||||
s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
|
||||
s->ll4 = BZALLOC(
|
||||
((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
|
||||
);
|
||||
if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
|
||||
} else {
|
||||
s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
|
||||
if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
|
||||
}
|
||||
|
||||
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
||||
|
||||
if (uc == 0x17) goto endhdr_2;
|
||||
if (uc != 0x31) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_2, uc);
|
||||
if (uc != 0x41) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_3, uc);
|
||||
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_4, uc);
|
||||
if (uc != 0x26) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_5, uc);
|
||||
if (uc != 0x53) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_6, uc);
|
||||
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->currBlockNo++;
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
|
||||
|
||||
s->storedBlockCRC = 0;
|
||||
GET_UCHAR(BZ_X_BCRC_1, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_2, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_3, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_4, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
|
||||
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
|
||||
|
||||
s->origPtr = 0;
|
||||
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
|
||||
if (s->origPtr < 0)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
if (s->origPtr > 10 + 100000*s->blockSize100k)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*--- Receive the mapping table ---*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
GET_BIT(BZ_X_MAPPING_1, uc);
|
||||
if (uc == 1)
|
||||
s->inUse16[i] = True; else
|
||||
s->inUse16[i] = False;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) s->inUse[i] = False;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (s->inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
GET_BIT(BZ_X_MAPPING_2, uc);
|
||||
if (uc == 1) s->inUse[i * 16 + j] = True;
|
||||
}
|
||||
makeMaps_d ( s );
|
||||
if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
|
||||
alphaSize = s->nInUse+2;
|
||||
|
||||
/*--- Now the selectors ---*/
|
||||
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
|
||||
if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
|
||||
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
|
||||
if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
j = 0;
|
||||
while (True) {
|
||||
GET_BIT(BZ_X_SELECTOR_3, uc);
|
||||
if (uc == 0) break;
|
||||
j++;
|
||||
if (j >= nGroups) RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
|
||||
/*--- Undo the MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], tmp, v;
|
||||
for (v = 0; v < nGroups; v++) pos[v] = v;
|
||||
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
v = s->selectorMtf[i];
|
||||
tmp = pos[v];
|
||||
while (v > 0) { pos[v] = pos[v-1]; v--; }
|
||||
pos[0] = tmp;
|
||||
s->selector[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Now the coding tables ---*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
GET_BITS(BZ_X_CODING_1, curr, 5);
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (True) {
|
||||
if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
|
||||
GET_BIT(BZ_X_CODING_2, uc);
|
||||
if (uc == 0) break;
|
||||
GET_BIT(BZ_X_CODING_3, uc);
|
||||
if (uc == 0) curr++; else curr--;
|
||||
}
|
||||
s->len[t][i] = curr;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Create the Huffman decoding tables ---*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||
}
|
||||
BZ2_hbCreateDecodeTables (
|
||||
&(s->limit[t][0]),
|
||||
&(s->base[t][0]),
|
||||
&(s->perm[t][0]),
|
||||
&(s->len[t][0]),
|
||||
minLen, maxLen, alphaSize
|
||||
);
|
||||
s->minLens[t] = minLen;
|
||||
}
|
||||
|
||||
/*--- Now the MTF values ---*/
|
||||
|
||||
EOB = s->nInUse+1;
|
||||
nblockMAX = 100000 * s->blockSize100k;
|
||||
groupNo = -1;
|
||||
groupPos = 0;
|
||||
|
||||
for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
|
||||
|
||||
/*-- MTF init --*/
|
||||
{
|
||||
Int32 ii, jj, kk;
|
||||
kk = MTFA_SIZE-1;
|
||||
for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
|
||||
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||
s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
|
||||
kk--;
|
||||
}
|
||||
s->mtfbase[ii] = kk + 1;
|
||||
}
|
||||
}
|
||||
/*-- end MTF init --*/
|
||||
|
||||
nblock = 0;
|
||||
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
|
||||
|
||||
while (True) {
|
||||
|
||||
if (nextSym == EOB) break;
|
||||
|
||||
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
|
||||
|
||||
es = -1;
|
||||
N = 1;
|
||||
do {
|
||||
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
|
||||
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
|
||||
N = N * 2;
|
||||
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
|
||||
}
|
||||
while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
|
||||
|
||||
es++;
|
||||
uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
|
||||
s->unzftab[uc] += es;
|
||||
|
||||
if (s->smallDecompress)
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
s->ll16[nblock] = (UInt16)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
}
|
||||
else
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
s->tt[nblock] = (UInt32)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
};
|
||||
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- uc = MTF ( nextSym-1 ) --*/
|
||||
{
|
||||
Int32 ii, jj, kk, pp, lno, off;
|
||||
UInt32 nn;
|
||||
nn = (UInt32)(nextSym - 1);
|
||||
|
||||
if (nn < MTFL_SIZE) {
|
||||
/* avoid general-case expense */
|
||||
pp = s->mtfbase[0];
|
||||
uc = s->mtfa[pp+nn];
|
||||
while (nn > 3) {
|
||||
Int32 z = pp+nn;
|
||||
s->mtfa[(z) ] = s->mtfa[(z)-1];
|
||||
s->mtfa[(z)-1] = s->mtfa[(z)-2];
|
||||
s->mtfa[(z)-2] = s->mtfa[(z)-3];
|
||||
s->mtfa[(z)-3] = s->mtfa[(z)-4];
|
||||
nn -= 4;
|
||||
}
|
||||
while (nn > 0) {
|
||||
s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
|
||||
};
|
||||
s->mtfa[pp] = uc;
|
||||
} else {
|
||||
/* general case */
|
||||
lno = nn / MTFL_SIZE;
|
||||
off = nn % MTFL_SIZE;
|
||||
pp = s->mtfbase[lno] + off;
|
||||
uc = s->mtfa[pp];
|
||||
while (pp > s->mtfbase[lno]) {
|
||||
s->mtfa[pp] = s->mtfa[pp-1]; pp--;
|
||||
};
|
||||
s->mtfbase[lno]++;
|
||||
while (lno > 0) {
|
||||
s->mtfbase[lno]--;
|
||||
s->mtfa[s->mtfbase[lno]]
|
||||
= s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
|
||||
lno--;
|
||||
}
|
||||
s->mtfbase[0]--;
|
||||
s->mtfa[s->mtfbase[0]] = uc;
|
||||
if (s->mtfbase[0] == 0) {
|
||||
kk = MTFA_SIZE-1;
|
||||
for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
|
||||
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||
s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
|
||||
kk--;
|
||||
}
|
||||
s->mtfbase[ii] = kk + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-- end uc = MTF ( nextSym-1 ) --*/
|
||||
|
||||
s->unzftab[s->seqToUnseq[uc]]++;
|
||||
if (s->smallDecompress)
|
||||
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
|
||||
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
|
||||
nblock++;
|
||||
|
||||
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we know what nblock is, we can do a better sanity
|
||||
check on s->origPtr.
|
||||
*/
|
||||
if (s->origPtr < 0 || s->origPtr >= nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- Set up cftab to facilitate generation of T^(-1) --*/
|
||||
s->cftab[0] = 0;
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
|
||||
/* s->cftab[i] can legitimately be == nblock */
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
s->state_out_len = 0;
|
||||
s->state_out_ch = 0;
|
||||
BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
|
||||
s->state = BZ_X_OUTPUT;
|
||||
if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
|
||||
|
||||
if (s->smallDecompress) {
|
||||
|
||||
/*-- Make a copy of cftab, used in generation of T --*/
|
||||
for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
|
||||
|
||||
/*-- compute the T vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->ll16[i]);
|
||||
SET_LL(i, s->cftabCopy[uc]);
|
||||
s->cftabCopy[uc]++;
|
||||
}
|
||||
|
||||
/*-- Compute T^(-1) by pointer reversal on T --*/
|
||||
i = s->origPtr;
|
||||
j = GET_LL(i);
|
||||
do {
|
||||
Int32 tmp = GET_LL(j);
|
||||
SET_LL(j, i);
|
||||
i = j;
|
||||
j = tmp;
|
||||
}
|
||||
while (i != s->origPtr);
|
||||
|
||||
s->tPos = s->origPtr;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||
} else {
|
||||
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*-- compute the T^(-1) vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->tt[i] & 0xff);
|
||||
s->tt[s->cftab[uc]] |= (i << 8);
|
||||
s->cftab[uc]++;
|
||||
}
|
||||
|
||||
s->tPos = s->tt[s->origPtr] >> 8;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||
} else {
|
||||
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RETURN(BZ_OK);
|
||||
|
||||
|
||||
|
||||
endhdr_2:
|
||||
|
||||
GET_UCHAR(BZ_X_ENDHDR_2, uc);
|
||||
if (uc != 0x72) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_3, uc);
|
||||
if (uc != 0x45) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_4, uc);
|
||||
if (uc != 0x38) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_5, uc);
|
||||
if (uc != 0x50) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_6, uc);
|
||||
if (uc != 0x90) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->storedCombinedCRC = 0;
|
||||
GET_UCHAR(BZ_X_CCRC_1, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_2, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_3, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_4, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
|
||||
s->state = BZ_X_IDLE;
|
||||
RETURN(BZ_STREAM_END);
|
||||
|
||||
default: AssertH ( False, 4001 );
|
||||
}
|
||||
|
||||
AssertH ( False, 4002 );
|
||||
|
||||
save_state_and_return:
|
||||
|
||||
s->save_i = i;
|
||||
s->save_j = j;
|
||||
s->save_t = t;
|
||||
s->save_alphaSize = alphaSize;
|
||||
s->save_nGroups = nGroups;
|
||||
s->save_nSelectors = nSelectors;
|
||||
s->save_EOB = EOB;
|
||||
s->save_groupNo = groupNo;
|
||||
s->save_groupPos = groupPos;
|
||||
s->save_nextSym = nextSym;
|
||||
s->save_nblockMAX = nblockMAX;
|
||||
s->save_nblock = nblock;
|
||||
s->save_es = es;
|
||||
s->save_N = N;
|
||||
s->save_curr = curr;
|
||||
s->save_zt = zt;
|
||||
s->save_zn = zn;
|
||||
s->save_zvec = zvec;
|
||||
s->save_zj = zj;
|
||||
s->save_gSel = gSel;
|
||||
s->save_gMinlen = gMinlen;
|
||||
s->save_gLimit = gLimit;
|
||||
s->save_gBase = gBase;
|
||||
s->save_gPerm = gPerm;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end decompress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
205
vendor/stormlib-9/src/bzip2/huffman.c
vendored
Normal file
205
vendor/stormlib-9/src/bzip2/huffman.c
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Huffman coding low-level stuff ---*/
|
||||
/*--- huffman.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
|
||||
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
|
||||
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
|
||||
|
||||
#define ADDWEIGHTS(zw1,zw2) \
|
||||
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
|
||||
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
|
||||
|
||||
#define UPHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, tmp; \
|
||||
zz = z; tmp = heap[zz]; \
|
||||
while (weight[tmp] < weight[heap[zz >> 1]]) { \
|
||||
heap[zz] = heap[zz >> 1]; \
|
||||
zz >>= 1; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
#define DOWNHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, yy, tmp; \
|
||||
zz = z; tmp = heap[zz]; \
|
||||
while (True) { \
|
||||
yy = zz << 1; \
|
||||
if (yy > nHeap) break; \
|
||||
if (yy < nHeap && \
|
||||
weight[heap[yy+1]] < weight[heap[yy]]) \
|
||||
yy++; \
|
||||
if (weight[tmp] < weight[heap[yy]]) break; \
|
||||
heap[zz] = heap[yy]; \
|
||||
zz = yy; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbMakeCodeLengths ( UChar *len,
|
||||
Int32 *freq,
|
||||
Int32 alphaSize,
|
||||
Int32 maxLen )
|
||||
{
|
||||
/*--
|
||||
Nodes and heap entries run from 1. Entry 0
|
||||
for both the heap and nodes is a sentinel.
|
||||
--*/
|
||||
Int32 nNodes, nHeap, n1, n2, i, j, k;
|
||||
Bool tooLong;
|
||||
|
||||
Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
|
||||
Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||
Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
|
||||
|
||||
while (True) {
|
||||
|
||||
nNodes = alphaSize;
|
||||
nHeap = 0;
|
||||
|
||||
heap[0] = 0;
|
||||
weight[0] = 0;
|
||||
parent[0] = -2;
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
parent[i] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = i;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
|
||||
|
||||
while (nHeap > 1) {
|
||||
n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||
n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||
nNodes++;
|
||||
parent[n1] = parent[n2] = nNodes;
|
||||
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
|
||||
parent[nNodes] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = nNodes;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
|
||||
|
||||
tooLong = False;
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = 0;
|
||||
k = i;
|
||||
while (parent[k] >= 0) { k = parent[k]; j++; }
|
||||
len[i-1] = j;
|
||||
if (j > maxLen) tooLong = True;
|
||||
}
|
||||
|
||||
if (! tooLong) break;
|
||||
|
||||
/* 17 Oct 04: keep-going condition for the following loop used
|
||||
to be 'i < alphaSize', which missed the last element,
|
||||
theoretically leading to the possibility of the compressor
|
||||
looping. However, this count-scaling step is only needed if
|
||||
one of the generated Huffman code words is longer than
|
||||
maxLen, which up to and including version 1.0.2 was 20 bits,
|
||||
which is extremely unlikely. In version 1.0.3 maxLen was
|
||||
changed to 17 bits, which has minimal effect on compression
|
||||
ratio, but does mean this scaling step is used from time to
|
||||
time, enough to verify that it works.
|
||||
|
||||
This means that bzip2-1.0.3 and later will only produce
|
||||
Huffman codes with a maximum length of 17 bits. However, in
|
||||
order to preserve backwards compatibility with bitstreams
|
||||
produced by versions pre-1.0.3, the decompressor must still
|
||||
handle lengths of up to 20. */
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = weight[i] >> 8;
|
||||
j = 1 + (j / 2);
|
||||
weight[i] = j << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbAssignCodes ( Int32 *code,
|
||||
UChar *length,
|
||||
Int32 minLen,
|
||||
Int32 maxLen,
|
||||
Int32 alphaSize )
|
||||
{
|
||||
Int32 n, vec, i;
|
||||
|
||||
vec = 0;
|
||||
for (n = minLen; n <= maxLen; n++) {
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
if (length[i] == n) { code[i] = vec; vec++; };
|
||||
vec <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbCreateDecodeTables ( Int32 *limit,
|
||||
Int32 *base,
|
||||
Int32 *perm,
|
||||
UChar *length,
|
||||
Int32 minLen,
|
||||
Int32 maxLen,
|
||||
Int32 alphaSize )
|
||||
{
|
||||
Int32 pp, i, j, vec;
|
||||
|
||||
pp = 0;
|
||||
for (i = minLen; i <= maxLen; i++)
|
||||
for (j = 0; j < alphaSize; j++)
|
||||
if (length[j] == i) { perm[pp] = j; pp++; };
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
|
||||
for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
|
||||
|
||||
for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
|
||||
vec = 0;
|
||||
|
||||
for (i = minLen; i <= maxLen; i++) {
|
||||
vec += (base[i+1] - base[i]);
|
||||
limit[i] = vec-1;
|
||||
vec <<= 1;
|
||||
}
|
||||
for (i = minLen + 1; i <= maxLen; i++)
|
||||
base[i] = ((limit[i-1] + 1) << 1) - base[i];
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end huffman.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
84
vendor/stormlib-9/src/bzip2/randtable.c
vendored
Normal file
84
vendor/stormlib-9/src/bzip2/randtable.c
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for randomising repetitive blocks ---*/
|
||||
/*--- randtable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
Int32 BZ2_rNums[512] = {
|
||||
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
||||
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
||||
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
||||
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
||||
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
||||
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
||||
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
||||
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
||||
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
||||
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
||||
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
||||
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
||||
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
||||
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
||||
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
||||
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
||||
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
||||
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
||||
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
||||
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
||||
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
||||
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
||||
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
||||
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
||||
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
||||
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
||||
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
||||
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
||||
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
||||
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
||||
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
||||
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
||||
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
||||
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
||||
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
||||
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
||||
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
||||
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
||||
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
||||
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
||||
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
||||
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
||||
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
||||
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
||||
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
||||
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
||||
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
||||
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
||||
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
||||
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
||||
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
||||
936, 638
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end randtable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
895
vendor/stormlib-9/src/huffman/huff.cpp
vendored
Normal file
895
vendor/stormlib-9/src/huffman/huff.cpp
vendored
Normal file
@ -0,0 +1,895 @@
|
||||
/*****************************************************************************/
|
||||
/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This module contains Huffmann (de)compression methods */
|
||||
/* */
|
||||
/* Authors : Ladislav Zezula (ladik@zezula.net) */
|
||||
/* ShadowFlare (BlakFlare@hotmail.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */
|
||||
/* 03.05.03 1.00 Lad Added compression methods */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
|
||||
/* 09.01.13 3.00 Lad Refactored, beautified, documented :-) */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "huff.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Table of byte-to-weight values
|
||||
|
||||
// Table for (de)compression. Every compression type has 258 entries
|
||||
static unsigned char ByteToWeight_00[] =
|
||||
{
|
||||
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x01
|
||||
static unsigned char ByteToWeight_01[] =
|
||||
{
|
||||
0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
|
||||
0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
|
||||
0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
|
||||
0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
|
||||
0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
|
||||
0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
|
||||
0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
|
||||
0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
|
||||
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
|
||||
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
|
||||
0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
|
||||
0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x02
|
||||
static unsigned char ByteToWeight_02[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
|
||||
0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
|
||||
0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
|
||||
0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
|
||||
0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
|
||||
0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x03
|
||||
static unsigned char ByteToWeight_03[] =
|
||||
{
|
||||
0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
|
||||
0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
|
||||
0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
|
||||
0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
|
||||
0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
|
||||
0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
|
||||
0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
|
||||
0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x04
|
||||
static unsigned char ByteToWeight_04[] =
|
||||
{
|
||||
0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x05
|
||||
static unsigned char ByteToWeight_05[] =
|
||||
{
|
||||
0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
|
||||
0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
|
||||
0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
|
||||
0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x06
|
||||
static unsigned char ByteToWeight_06[] =
|
||||
{
|
||||
0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x07
|
||||
static unsigned char ByteToWeight_07[] =
|
||||
{
|
||||
0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
// Data for compression type 0x08
|
||||
static unsigned char ByteToWeight_08[] =
|
||||
{
|
||||
0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
|
||||
0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
|
||||
0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
static unsigned char * WeightTables[0x09] =
|
||||
{
|
||||
ByteToWeight_00,
|
||||
ByteToWeight_01,
|
||||
ByteToWeight_02,
|
||||
ByteToWeight_03,
|
||||
ByteToWeight_04,
|
||||
ByteToWeight_05,
|
||||
ByteToWeight_06,
|
||||
ByteToWeight_07,
|
||||
ByteToWeight_08
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Debug/diagnostics
|
||||
|
||||
#ifdef _DEBUG
|
||||
void DumpHuffmannTree(THTreeItem * pItem)
|
||||
{
|
||||
THTreeItem * pChildLo; // Item with the lower weight
|
||||
THTreeItem * pChildHi; // Item with the higher weight
|
||||
|
||||
// Get the lower-weight branch
|
||||
pChildLo = pItem->pChildLo;
|
||||
if(pChildLo != NULL)
|
||||
{
|
||||
// Get the higher-weight branch
|
||||
pChildHi = pChildLo->pPrev;
|
||||
|
||||
// Parse the lower-weight branch
|
||||
DumpHuffmannTree(pChildHi);
|
||||
DumpHuffmannTree(pChildLo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TInputStream functions
|
||||
|
||||
TInputStream::TInputStream(void * pvInBuffer, size_t cbInBuffer)
|
||||
{
|
||||
pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer;
|
||||
pbInBuffer = (unsigned char *)pvInBuffer;
|
||||
BitBuffer = 0;
|
||||
BitCount = 0;
|
||||
}
|
||||
|
||||
// Gets one bit from input stream
|
||||
unsigned int TInputStream::Get1Bit()
|
||||
{
|
||||
unsigned int OneBit = 0;
|
||||
|
||||
// Ensure that the input stream is reloaded, if there are no bits left
|
||||
if(BitCount == 0)
|
||||
{
|
||||
// Refill the bit buffer
|
||||
BitBuffer = *pbInBuffer++;
|
||||
BitCount = 8;
|
||||
}
|
||||
|
||||
// Copy the bit from bit buffer to the variable
|
||||
OneBit = (BitBuffer & 0x01);
|
||||
BitBuffer >>= 1;
|
||||
BitCount--;
|
||||
|
||||
return OneBit;
|
||||
}
|
||||
|
||||
// Gets the whole byte from the input stream.
|
||||
unsigned int TInputStream::Get8Bits()
|
||||
{
|
||||
unsigned int dwReloadByte = 0;
|
||||
unsigned int dwOneByte = 0;
|
||||
|
||||
// If there is not enough bits to get the value,
|
||||
// we have to add 8 more bits from the input buffer
|
||||
if(BitCount < 8)
|
||||
{
|
||||
dwReloadByte = *pbInBuffer++;
|
||||
BitBuffer |= dwReloadByte << BitCount;
|
||||
BitCount += 8;
|
||||
}
|
||||
|
||||
// Return the lowest 8 its
|
||||
dwOneByte = (BitBuffer & 0xFF);
|
||||
BitBuffer >>= 8;
|
||||
BitCount -= 8;
|
||||
return dwOneByte;
|
||||
}
|
||||
|
||||
// Gets 7 bits from the stream. DOES NOT remove the bits from input stream
|
||||
bool TInputStream::Peek7Bits(unsigned int & Value)
|
||||
{
|
||||
unsigned int Value8Bits = 0;
|
||||
|
||||
// If there is not enough bits to get the value,
|
||||
// we have to add 8 more bits from the input buffer
|
||||
if(BitCount < 7)
|
||||
{
|
||||
// Load additional 8 bits. Be careful if we have no more data
|
||||
if(pbInBuffer >= pbInBufferEnd)
|
||||
return false;
|
||||
Value8Bits = *pbInBuffer++;
|
||||
|
||||
// Add these 8 bits to the bit buffer
|
||||
BitBuffer |= Value8Bits << BitCount;
|
||||
BitCount += 8;
|
||||
}
|
||||
|
||||
// Return 7 bits of data. DO NOT remove them from the input stream
|
||||
Value = (BitBuffer & 0x7F);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TInputStream::SkipBits(unsigned int dwBitsToSkip)
|
||||
{
|
||||
unsigned int dwReloadByte = 0;
|
||||
|
||||
// If there is not enough bits in the buffer,
|
||||
// we have to add 8 more bits from the input buffer
|
||||
if(BitCount < dwBitsToSkip)
|
||||
{
|
||||
dwReloadByte = *pbInBuffer++;
|
||||
BitBuffer |= dwReloadByte << BitCount;
|
||||
BitCount += 8;
|
||||
}
|
||||
|
||||
// Skip the remaining bits
|
||||
BitBuffer >>= dwBitsToSkip;
|
||||
BitCount -= dwBitsToSkip;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TOutputStream functions
|
||||
|
||||
TOutputStream::TOutputStream(void * pvOutBuffer, size_t cbOutLength)
|
||||
{
|
||||
pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength;
|
||||
pbOutBuffer = (unsigned char *)pvOutBuffer;
|
||||
BitBuffer = 0;
|
||||
BitCount = 0;
|
||||
}
|
||||
|
||||
void TOutputStream::PutBits(unsigned int dwValue, unsigned int nBitCount)
|
||||
{
|
||||
BitBuffer |= (dwValue << BitCount);
|
||||
BitCount += nBitCount;
|
||||
|
||||
// Flush completed bytes
|
||||
while(BitCount >= 8)
|
||||
{
|
||||
if(pbOutBuffer < pbOutBufferEnd)
|
||||
*pbOutBuffer++ = (unsigned char)BitBuffer;
|
||||
|
||||
BitBuffer >>= 8;
|
||||
BitCount -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void TOutputStream::Flush()
|
||||
{
|
||||
while(BitCount != 0)
|
||||
{
|
||||
if(pbOutBuffer < pbOutBufferEnd)
|
||||
*pbOutBuffer++ = (unsigned char)BitBuffer;
|
||||
|
||||
BitBuffer >>= 8;
|
||||
BitCount -= ((BitCount > 8) ? 8 : BitCount);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods of the THTreeItem struct
|
||||
|
||||
void THTreeItem::RemoveItem()
|
||||
{
|
||||
if(pNext != NULL)
|
||||
{
|
||||
pPrev->pNext = pNext;
|
||||
pNext->pPrev = pPrev;
|
||||
pNext = pPrev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// THuffmannTree class functions
|
||||
|
||||
THuffmannTree::THuffmannTree(bool bCompression)
|
||||
{
|
||||
pFirst = pLast = LIST_HEAD();
|
||||
MinValidValue = 1;
|
||||
ItemsUsed = 0;
|
||||
bIsCmp0 = 0;
|
||||
|
||||
memset(ItemsByByte, 0, sizeof(ItemsByByte));
|
||||
|
||||
// If we are going to decompress data, we need to invalidate all item links
|
||||
// We do so by zeroing their ValidValue, so it becomes lower MinValidValue
|
||||
if(bCompression == false)
|
||||
{
|
||||
memset(QuickLinks, 0, sizeof(QuickLinks));
|
||||
}
|
||||
}
|
||||
|
||||
THuffmannTree::~THuffmannTree()
|
||||
{
|
||||
// Our Huffmann tree does not use any memory allocations,
|
||||
// so we don't need to do eny code in the destructor
|
||||
}
|
||||
|
||||
void THuffmannTree::LinkTwoItems(THTreeItem * pItem1, THTreeItem * pItem2)
|
||||
{
|
||||
pItem2->pNext = pItem1->pNext;
|
||||
pItem2->pPrev = pItem1->pNext->pPrev;
|
||||
pItem1->pNext->pPrev = pItem2;
|
||||
pItem1->pNext = pItem2;
|
||||
}
|
||||
|
||||
// Inserts item into the tree (?)
|
||||
void THuffmannTree::InsertItem(THTreeItem * pNewItem, TInsertPoint InsertPoint, THTreeItem * pInsertPoint)
|
||||
{
|
||||
// Remove the item from the tree
|
||||
pNewItem->RemoveItem();
|
||||
|
||||
if(pInsertPoint == NULL)
|
||||
pInsertPoint = LIST_HEAD();
|
||||
|
||||
switch(InsertPoint)
|
||||
{
|
||||
case InsertAfter:
|
||||
LinkTwoItems(pInsertPoint, pNewItem);
|
||||
return;
|
||||
|
||||
case InsertBefore:
|
||||
pNewItem->pNext = pInsertPoint; // Set next item (or pointer to pointer to first item)
|
||||
pNewItem->pPrev = pInsertPoint->pPrev; // Set prev item (or last item in the tree)
|
||||
pInsertPoint->pPrev->pNext = pNewItem;
|
||||
pInsertPoint->pPrev = pNewItem; // Set the next/last item
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
THTreeItem * THuffmannTree::FindHigherOrEqualItem(THTreeItem * pItem, unsigned int Weight)
|
||||
{
|
||||
// Parse all existing items
|
||||
if(pItem != NULL)
|
||||
{
|
||||
while(pItem != LIST_HEAD())
|
||||
{
|
||||
if(pItem->Weight >= Weight)
|
||||
return pItem;
|
||||
|
||||
pItem = pItem->pPrev;
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, we just get the first item
|
||||
return LIST_HEAD();
|
||||
}
|
||||
|
||||
THTreeItem * THuffmannTree::CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint)
|
||||
{
|
||||
THTreeItem * pNewItem = NULL;
|
||||
|
||||
// Don't let the item buffer run out of space
|
||||
if(ItemsUsed < HUFF_ITEM_COUNT)
|
||||
{
|
||||
// Allocate new item from the item pool
|
||||
pNewItem = &ItemBuffer[ItemsUsed++];
|
||||
|
||||
// Insert this item to the top of the tree
|
||||
InsertItem(pNewItem, InsertPoint, NULL);
|
||||
|
||||
// Fill the rest of the item
|
||||
pNewItem->DecompressedValue = DecompressedValue;
|
||||
pNewItem->Weight = Weight;
|
||||
pNewItem->pParent = NULL;
|
||||
pNewItem->pChildLo = NULL;
|
||||
}
|
||||
|
||||
return pNewItem;
|
||||
}
|
||||
|
||||
unsigned int THuffmannTree::FixupItemPosByWeight(THTreeItem * pNewItem, unsigned int MaxWeight)
|
||||
{
|
||||
THTreeItem * pHigherItem;
|
||||
|
||||
if(pNewItem->Weight < MaxWeight)
|
||||
{
|
||||
// Find an item that has higher weight than this one
|
||||
pHigherItem = FindHigherOrEqualItem(pLast, pNewItem->Weight);
|
||||
|
||||
// Remove the item and put it to the new position
|
||||
pNewItem->RemoveItem();
|
||||
LinkTwoItems(pHigherItem, pNewItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxWeight = pNewItem->Weight;
|
||||
}
|
||||
|
||||
// Return the (updated) maximum weight
|
||||
return MaxWeight;
|
||||
}
|
||||
|
||||
// Builds Huffman tree. Called with the first 8 bits loaded from input stream
|
||||
bool THuffmannTree::BuildTree(unsigned int CompressionType)
|
||||
{
|
||||
THTreeItem * pNewItem;
|
||||
THTreeItem * pChildLo;
|
||||
THTreeItem * pChildHi;
|
||||
unsigned char * WeightTable;
|
||||
unsigned int MaxWeight; // [ESP+10] - The greatest character found in table
|
||||
|
||||
// Clear all pointers in HTree item array
|
||||
memset(ItemsByByte, 0, sizeof(ItemsByByte));
|
||||
MaxWeight = 0;
|
||||
|
||||
// Ensure that the compression type is in range
|
||||
if((CompressionType & 0x0F) > 0x08)
|
||||
return false;
|
||||
WeightTable = WeightTables[CompressionType & 0x0F];
|
||||
|
||||
// Build the linear list of entries that is sorted by byte weight
|
||||
for(unsigned int i = 0; i < 0x100; i++)
|
||||
{
|
||||
// Skip all the bytes which are zero.
|
||||
if(WeightTable[i] != 0)
|
||||
{
|
||||
// Create new tree item
|
||||
ItemsByByte[i] = pNewItem = CreateNewItem(i, WeightTable[i], InsertAfter);
|
||||
|
||||
// We need to put the item to the right place in the list
|
||||
MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert termination entries at the end of the list
|
||||
ItemsByByte[0x100] = CreateNewItem(0x100, 1, InsertBefore);
|
||||
ItemsByByte[0x101] = CreateNewItem(0x101, 1, InsertBefore);
|
||||
|
||||
// Now we need to build the tree. We start at the last entry
|
||||
// and go backwards to the first one
|
||||
pChildLo = pLast;
|
||||
|
||||
// Work as long as both children are valid
|
||||
// pChildHi is child with higher weight, pChildLo is the one with lower weight
|
||||
while(pChildLo != LIST_HEAD())
|
||||
{
|
||||
// Also get and verify the higher-weight child
|
||||
pChildHi = pChildLo->pPrev;
|
||||
if(pChildHi == LIST_HEAD())
|
||||
break;
|
||||
|
||||
// Create new parent item for the children
|
||||
pNewItem = CreateNewItem(0, pChildHi->Weight + pChildLo->Weight, InsertAfter);
|
||||
if(pNewItem == NULL)
|
||||
return false;
|
||||
|
||||
// Link both child items to their new parent
|
||||
pChildLo->pParent = pNewItem;
|
||||
pChildHi->pParent = pNewItem;
|
||||
pNewItem->pChildLo = pChildLo;
|
||||
|
||||
// Fixup the item's position by its weight
|
||||
MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight);
|
||||
|
||||
// Get the previous lower-weight child
|
||||
pChildLo = pChildHi->pPrev;
|
||||
}
|
||||
|
||||
// Initialize the MinValidValue to 1, which invalidates all quick-link items
|
||||
MinValidValue = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void THuffmannTree::IncWeightsAndRebalance(THTreeItem * pItem)
|
||||
{
|
||||
THTreeItem * pHigherItem; // A previous item with greater or equal weight
|
||||
THTreeItem * pChildHi; // The higher-weight child
|
||||
THTreeItem * pChildLo; // The lower-weight child
|
||||
THTreeItem * pParent;
|
||||
|
||||
// Climb up the tree and increment weight of each tree item
|
||||
for(; pItem != NULL; pItem = pItem->pParent)
|
||||
{
|
||||
// Increment the item's weight
|
||||
pItem->Weight++;
|
||||
|
||||
// Find a previous item with equal or greater weight, which is not equal to this item
|
||||
pHigherItem = FindHigherOrEqualItem(pItem->pPrev, pItem->Weight);
|
||||
pChildHi = pHigherItem->pNext;
|
||||
|
||||
// If the item is not equal to the tree item, we need to rebalance the tree
|
||||
if(pChildHi != pItem)
|
||||
{
|
||||
// Move the previous item to the RIGHT from the given item
|
||||
pChildHi->RemoveItem();
|
||||
LinkTwoItems(pItem, pChildHi);
|
||||
|
||||
// Move the given item AFTER the greater-weight tree item
|
||||
pItem->RemoveItem();
|
||||
LinkTwoItems(pHigherItem, pItem);
|
||||
|
||||
// We need to maintain the tree so that pChildHi->Weight is >= pChildLo->Weight.
|
||||
// Rebalance the tree accordingly.
|
||||
pChildLo = pChildHi->pParent->pChildLo;
|
||||
pParent = pItem->pParent;
|
||||
if(pParent->pChildLo == pItem)
|
||||
pParent->pChildLo = pChildHi;
|
||||
if(pChildLo == pChildHi)
|
||||
pChildHi->pParent->pChildLo = pItem;
|
||||
pParent = pItem->pParent;
|
||||
pItem->pParent = pChildHi->pParent;
|
||||
pChildHi->pParent = pParent;
|
||||
|
||||
// Increment the global valid value. This invalidates all quick-link items.
|
||||
MinValidValue++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2)
|
||||
{
|
||||
THTreeItem * pLastItem = pLast;
|
||||
THTreeItem * pChildHi;
|
||||
THTreeItem * pChildLo;
|
||||
|
||||
// Create higher-weight child
|
||||
pChildHi = CreateNewItem(Value1, pLastItem->Weight, InsertBefore);
|
||||
if(pChildHi != NULL)
|
||||
{
|
||||
pChildHi->pParent = pLastItem;
|
||||
ItemsByByte[Value1] = pChildHi;
|
||||
|
||||
// Create lower-weight child
|
||||
pChildLo = CreateNewItem(Value2, 0, InsertBefore);
|
||||
if(pChildLo != NULL)
|
||||
{
|
||||
pChildLo->pParent = pLastItem;
|
||||
pLastItem->pChildLo = pChildLo;
|
||||
ItemsByByte[Value2] = pChildLo;
|
||||
|
||||
IncWeightsAndRebalance(pChildLo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No more space in the tree buffer
|
||||
return false;
|
||||
}
|
||||
|
||||
void THuffmannTree::EncodeOneByte(TOutputStream * os, THTreeItem * pItem)
|
||||
{
|
||||
THTreeItem * pParent = pItem->pParent;
|
||||
unsigned int BitBuffer = 0;
|
||||
unsigned int BitCount = 0;
|
||||
|
||||
// Put 1's as long as there is parent
|
||||
while(pParent != NULL)
|
||||
{
|
||||
// Fill the bit buffer
|
||||
BitBuffer = (BitBuffer << 1) | ((pParent->pChildLo != pItem) ? 1 : 0);
|
||||
BitCount++;
|
||||
|
||||
// Move to the parent
|
||||
pItem = pParent;
|
||||
pParent = pParent->pParent;
|
||||
}
|
||||
|
||||
// Write the bits to the output stream
|
||||
os->PutBits(BitBuffer, BitCount);
|
||||
}
|
||||
|
||||
unsigned int THuffmannTree::DecodeOneByte(TInputStream * is)
|
||||
{
|
||||
THTreeItem * pItemLink = NULL;
|
||||
THTreeItem * pItem;
|
||||
unsigned int ItemLinkIndex;
|
||||
unsigned int BitCount = 0;
|
||||
bool bHasItemLinkIndex;
|
||||
|
||||
// Try to retrieve quick link index
|
||||
bHasItemLinkIndex = is->Peek7Bits(ItemLinkIndex);
|
||||
|
||||
// Is the quick-link item valid?
|
||||
if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue > MinValidValue)
|
||||
{
|
||||
// If that item needs less than 7 bits, we can get decompressed value directly
|
||||
if(QuickLinks[ItemLinkIndex].ValidBits <= 7)
|
||||
{
|
||||
is->SkipBits(QuickLinks[ItemLinkIndex].ValidBits);
|
||||
return QuickLinks[ItemLinkIndex].DecompressedValue;
|
||||
}
|
||||
|
||||
// Otherwise we cannot get decompressed value directly
|
||||
// but we can skip 7 levels of tree parsing
|
||||
pItem = QuickLinks[ItemLinkIndex].pItem;
|
||||
is->SkipBits(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just a sanity check
|
||||
if(pFirst == LIST_HEAD())
|
||||
return 0x1FF;
|
||||
|
||||
// We don't have the quick-link item, we need to parse the tree from its root
|
||||
pItem = pFirst;
|
||||
}
|
||||
|
||||
// Step down the tree until we find a terminal item
|
||||
while(pItem->pChildLo != NULL)
|
||||
{
|
||||
// If the next bit in the compressed stream is set, we get the higher-weight
|
||||
// child. Otherwise, get the lower-weight child.
|
||||
pItem = is->Get1Bit() ? pItem->pChildLo->pPrev : pItem->pChildLo;
|
||||
BitCount++;
|
||||
|
||||
// If the number of loaded bits reached 7,
|
||||
// remember the current item for storing into quick-link item array
|
||||
if(BitCount == 7)
|
||||
pItemLink = pItem;
|
||||
}
|
||||
|
||||
// If we didn't get the item from the quick-link array,
|
||||
// set the entry in it
|
||||
if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue < MinValidValue)
|
||||
{
|
||||
// If the current compressed byte was more than 7 bits,
|
||||
// set a quick-link item with pointer to tree item
|
||||
if(BitCount > 7)
|
||||
{
|
||||
QuickLinks[ItemLinkIndex].ValidValue = MinValidValue;
|
||||
QuickLinks[ItemLinkIndex].ValidBits = BitCount;
|
||||
QuickLinks[ItemLinkIndex].pItem = pItemLink;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Limit the quick-decompress item to lower amount of bits
|
||||
// Coverity fix 84457: (x >> 32) has undefined behavior
|
||||
ItemLinkIndex = (BitCount != 0) ? ItemLinkIndex & (0xFFFFFFFF >> (32 - BitCount)) : 0;
|
||||
while(ItemLinkIndex < LINK_ITEM_COUNT)
|
||||
{
|
||||
// Fill the quick-decompress item
|
||||
QuickLinks[ItemLinkIndex].ValidValue = MinValidValue;
|
||||
QuickLinks[ItemLinkIndex].ValidBits = BitCount;
|
||||
QuickLinks[ItemLinkIndex].DecompressedValue = pItem->DecompressedValue;
|
||||
|
||||
// Increment the index
|
||||
ItemLinkIndex += (1 << BitCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the decompressed value from the found item
|
||||
return pItem->DecompressedValue;
|
||||
}
|
||||
|
||||
unsigned int THuffmannTree::Compress(TOutputStream * os, void * pvInBuffer, int cbInBuffer, int CompressionType)
|
||||
{
|
||||
unsigned char * pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer;
|
||||
unsigned char * pbInBuffer = (unsigned char *)pvInBuffer;
|
||||
unsigned char * pbOutBuff = os->pbOutBuffer;
|
||||
unsigned char InputByte;
|
||||
|
||||
if(!BuildTree(CompressionType))
|
||||
return 0;
|
||||
bIsCmp0 = (CompressionType == 0);
|
||||
|
||||
// Store the compression type into output buffer
|
||||
os->PutBits(CompressionType, 8);
|
||||
|
||||
// Process the entire input buffer
|
||||
while(pbInBuffer < pbInBufferEnd)
|
||||
{
|
||||
// Get the (next) byte from the input buffer
|
||||
InputByte = *pbInBuffer++;
|
||||
|
||||
// Do we have an item for such input value?
|
||||
if(ItemsByByte[InputByte] == NULL)
|
||||
{
|
||||
// Encode the relationship
|
||||
EncodeOneByte(os, ItemsByByte[0x101]);
|
||||
|
||||
// Store the loaded byte into output stream
|
||||
os->PutBits(InputByte, 8);
|
||||
|
||||
if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte))
|
||||
return 0;
|
||||
|
||||
if(bIsCmp0)
|
||||
{
|
||||
IncWeightsAndRebalance(ItemsByByte[InputByte]);
|
||||
continue;
|
||||
}
|
||||
|
||||
IncWeightsAndRebalance(ItemsByByte[InputByte]);
|
||||
}
|
||||
else
|
||||
{
|
||||
EncodeOneByte(os, ItemsByByte[InputByte]);
|
||||
}
|
||||
|
||||
if(bIsCmp0)
|
||||
{
|
||||
IncWeightsAndRebalance(ItemsByByte[InputByte]);
|
||||
}
|
||||
}
|
||||
|
||||
// Put the termination mark to the compressed stream
|
||||
EncodeOneByte(os, ItemsByByte[0x100]);
|
||||
|
||||
// Flush the remaining bits
|
||||
os->Flush();
|
||||
return (unsigned int)(os->pbOutBuffer - pbOutBuff);
|
||||
}
|
||||
|
||||
// Decompression using Huffman tree (1500E450)
|
||||
unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLength, TInputStream * is)
|
||||
{
|
||||
unsigned char * pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength;
|
||||
unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer;
|
||||
unsigned int DecompressedValue = 0;
|
||||
unsigned int CompressionType = 0;
|
||||
|
||||
// Test the output length. Must not be NULL.
|
||||
if(cbOutLength == 0)
|
||||
return 0;
|
||||
|
||||
// Get the compression type from the input stream
|
||||
CompressionType = is->Get8Bits();
|
||||
bIsCmp0 = (CompressionType == 0) ? 1 : 0;
|
||||
|
||||
// Build the Huffman tree
|
||||
if(!BuildTree(CompressionType))
|
||||
return 0;
|
||||
|
||||
// Process the entire input buffer until end of the stream
|
||||
while((DecompressedValue = DecodeOneByte(is)) != 0x100)
|
||||
{
|
||||
// Did an error occur?
|
||||
if(DecompressedValue == 0x1FF) // An error occurred
|
||||
return 0;
|
||||
|
||||
// Huffman tree needs to be modified
|
||||
if(DecompressedValue == 0x101)
|
||||
{
|
||||
// The decompressed byte is stored in the next 8 bits
|
||||
DecompressedValue = is->Get8Bits();
|
||||
|
||||
if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue))
|
||||
return 0;
|
||||
|
||||
if(bIsCmp0 == 0)
|
||||
IncWeightsAndRebalance(ItemsByByte[DecompressedValue]);
|
||||
}
|
||||
|
||||
// Store the byte to the output stream
|
||||
if(pbOutBuffer >= pbOutBufferEnd)
|
||||
break;
|
||||
*pbOutBuffer++ = (unsigned char)DecompressedValue;
|
||||
|
||||
if(bIsCmp0)
|
||||
{
|
||||
IncWeightsAndRebalance(ItemsByByte[DecompressedValue]);
|
||||
}
|
||||
}
|
||||
|
||||
return (unsigned int)(pbOutBuffer - (unsigned char *)pvOutBuffer);
|
||||
}
|
||||
|
||||
143
vendor/stormlib-9/src/huffman/huff.h
vendored
Normal file
143
vendor/stormlib-9/src/huffman/huff.h
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
/*****************************************************************************/
|
||||
/* huffman.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of huffman.h */
|
||||
/* 03.05.03 2.00 Lad Added compression */
|
||||
/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __HUFFMAN_H__
|
||||
#define __HUFFMAN_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define HUFF_ITEM_COUNT 0x203 // Number of items in the item pool
|
||||
#define LINK_ITEM_COUNT 0x80 // Maximum number of quick-link items
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures and classes
|
||||
|
||||
// Input stream for Huffmann decompression
|
||||
class TInputStream
|
||||
{
|
||||
public:
|
||||
|
||||
TInputStream(void * pvInBuffer, size_t cbInBuffer);
|
||||
unsigned int Get1Bit();
|
||||
unsigned int Get8Bits();
|
||||
bool Peek7Bits(unsigned int & Value);
|
||||
void SkipBits(unsigned int BitCount);
|
||||
|
||||
unsigned char * pbInBufferEnd; // End position in the the input buffer
|
||||
unsigned char * pbInBuffer; // Current position in the the input buffer
|
||||
unsigned int BitBuffer; // Input bit buffer
|
||||
unsigned int BitCount; // Number of bits remaining in 'dwBitBuff'
|
||||
};
|
||||
|
||||
|
||||
// Output stream for Huffmann compression
|
||||
class TOutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
TOutputStream(void * pvOutBuffer, size_t cbOutLength);
|
||||
void PutBits(unsigned int dwValue, unsigned int nBitCount);
|
||||
void Flush();
|
||||
|
||||
unsigned char * pbOutBufferEnd; // End position in the output buffer
|
||||
unsigned char * pbOutBuffer; // Current position in the output buffer
|
||||
unsigned int BitBuffer; // Bit buffer
|
||||
unsigned int BitCount; // Number of bits in the bit buffer
|
||||
};
|
||||
|
||||
// A virtual tree item that represents the head of the item list
|
||||
#define LIST_HEAD() ((THTreeItem *)(&pFirst))
|
||||
|
||||
enum TInsertPoint
|
||||
{
|
||||
InsertAfter = 1,
|
||||
InsertBefore = 2
|
||||
};
|
||||
|
||||
// Huffmann tree item
|
||||
struct THTreeItem
|
||||
{
|
||||
THTreeItem() { pPrev = pNext = NULL; DecompressedValue = 0; Weight = 0; pParent = pChildLo = NULL; }
|
||||
// ~THTreeItem() { RemoveItem(); }
|
||||
|
||||
void RemoveItem();
|
||||
// void RemoveEntry();
|
||||
|
||||
THTreeItem * pNext; // Pointer to lower-weight tree item
|
||||
THTreeItem * pPrev; // Pointer to higher-weight item
|
||||
unsigned int DecompressedValue; // 08 - Decompressed byte value (also index in the array)
|
||||
unsigned int Weight; // 0C - Weight
|
||||
THTreeItem * pParent; // 10 - Pointer to parent item (NULL if none)
|
||||
THTreeItem * pChildLo; // 14 - Pointer to the child with lower-weight child ("left child")
|
||||
};
|
||||
|
||||
|
||||
// Structure used for quick navigating in the huffmann tree.
|
||||
// Allows skipping up to 7 bits in the compressed stream, thus
|
||||
// decompressing a bit faster. Sometimes it can even get the decompressed
|
||||
// byte directly.
|
||||
struct TQuickLink
|
||||
{
|
||||
unsigned int ValidValue; // If greater than THuffmannTree::MinValidValue, the entry is valid
|
||||
unsigned int ValidBits; // Number of bits that are valid for this item link
|
||||
union
|
||||
{
|
||||
THTreeItem * pItem; // Pointer to the item within the Huffmann tree
|
||||
unsigned int DecompressedValue; // Value for direct decompression
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
|
||||
// for the decompression, I do not know actually if the class is really a Hufmann
|
||||
// tree. If someone knows the decompression details, please let me know
|
||||
class THuffmannTree
|
||||
{
|
||||
public:
|
||||
|
||||
THuffmannTree(bool bCompression);
|
||||
~THuffmannTree();
|
||||
|
||||
void LinkTwoItems(THTreeItem * pItem1, THTreeItem * pItem2);
|
||||
void InsertItem(THTreeItem * item, TInsertPoint InsertPoint, THTreeItem * item2);
|
||||
|
||||
THTreeItem * FindHigherOrEqualItem(THTreeItem * pItem, unsigned int Weight);
|
||||
THTreeItem * CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint);
|
||||
|
||||
unsigned int FixupItemPosByWeight(THTreeItem * pItem, unsigned int MaxWeight);
|
||||
bool BuildTree(unsigned int CompressionType);
|
||||
|
||||
void IncWeightsAndRebalance(THTreeItem * pItem);
|
||||
bool InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2);
|
||||
|
||||
void EncodeOneByte(TOutputStream * os, THTreeItem * pItem);
|
||||
unsigned int DecodeOneByte(TInputStream * is);
|
||||
|
||||
unsigned int Compress(TOutputStream * os, void * pvInBuffer, int cbInBuffer, int nCmpType);
|
||||
unsigned int Decompress(void * pvOutBuffer, unsigned int cbOutLength, TInputStream * is);
|
||||
|
||||
THTreeItem ItemBuffer[HUFF_ITEM_COUNT]; // Buffer for tree items. No memory allocation is needed
|
||||
unsigned int ItemsUsed; // Number of tree items used from ItemBuffer
|
||||
|
||||
// Head of the linear item list
|
||||
THTreeItem * pFirst; // Pointer to the highest weight item
|
||||
THTreeItem * pLast; // Pointer to the lowest weight item
|
||||
|
||||
THTreeItem * ItemsByByte[0x102]; // Array of item pointers, one for each possible byte value
|
||||
TQuickLink QuickLinks[LINK_ITEM_COUNT]; // Array of quick-link items
|
||||
|
||||
unsigned int MinValidValue; // A minimum value of TQDecompress::ValidValue to be considered valid
|
||||
unsigned int bIsCmp0; // 1 if compression type 0
|
||||
};
|
||||
|
||||
#endif // __HUFFMAN_H__
|
||||
24
vendor/stormlib-9/src/jenkins/lookup.h
vendored
Normal file
24
vendor/stormlib-9/src/jenkins/lookup.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __LOOKUP3_H__
|
||||
#define __LOOKUP3_H__
|
||||
|
||||
#ifdef WIN32
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
#include <stdint.h> /* defines uint32_t etc */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
uint32_t hashlittle(const void *key, size_t length, uint32_t initval);
|
||||
void hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LOOKUP3_H__
|
||||
1003
vendor/stormlib-9/src/jenkins/lookup3.c
vendored
Normal file
1003
vendor/stormlib-9/src/jenkins/lookup3.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
69
vendor/stormlib-9/src/libtomcrypt/src/hashes/hash_memory.c
vendored
Normal file
69
vendor/stormlib-9/src/libtomcrypt/src/hashes/hash_memory.c
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file hash_memory.c
|
||||
Hash memory helper, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Hash a block of memory and store the digest.
|
||||
@param hash The index of the hash you wish to use
|
||||
@param in The data you wish to hash
|
||||
@param inlen The length of the data to hash (octets)
|
||||
@param out [out] Where to store the digest
|
||||
@param outlen [in/out] Max size and resulting size of the digest
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
hash_state *md;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (*outlen < hash_descriptor[hash].hashsize) {
|
||||
*outlen = hash_descriptor[hash].hashsize;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
md = XMALLOC(sizeof(hash_state));
|
||||
if (md == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
err = hash_descriptor[hash].done(md, out);
|
||||
*outlen = hash_descriptor[hash].hashsize;
|
||||
LBL_ERR:
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
XFREE(md);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:23 $ */
|
||||
368
vendor/stormlib-9/src/libtomcrypt/src/hashes/md5.c
vendored
Normal file
368
vendor/stormlib-9/src/libtomcrypt/src/hashes/md5.c
vendored
Normal file
@ -0,0 +1,368 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
|
||||
/**
|
||||
@file md5.c
|
||||
LTC_MD5 hash function by Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_MD5
|
||||
|
||||
const struct ltc_hash_descriptor md5_desc =
|
||||
{
|
||||
"md5",
|
||||
3,
|
||||
16,
|
||||
64,
|
||||
|
||||
/* OID */
|
||||
{ 1, 2, 840, 113549, 2, 5, },
|
||||
6,
|
||||
|
||||
&md5_init,
|
||||
&md5_process,
|
||||
&md5_done,
|
||||
&md5_test,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define G(x,y,z) (y ^ (z & (y ^ x)))
|
||||
#define H(x,y,z) (x^y^z)
|
||||
#define I(x,y,z) (y^(x|(~z)))
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
|
||||
#define FF(a,b,c,d,M,s,t) \
|
||||
a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define GG(a,b,c,d,M,s,t) \
|
||||
a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define HH(a,b,c,d,M,s,t) \
|
||||
a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define II(a,b,c,d,M,s,t) \
|
||||
a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
static const unsigned char Worder[64] = {
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
|
||||
1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
|
||||
5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
|
||||
0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
|
||||
};
|
||||
|
||||
static const unsigned char Rorder[64] = {
|
||||
7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
|
||||
5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
|
||||
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
|
||||
6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
|
||||
};
|
||||
|
||||
static const ulong32 Korder[64] = {
|
||||
0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
|
||||
0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
|
||||
0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
|
||||
0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
|
||||
0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
|
||||
0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
|
||||
0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
|
||||
0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define FF(a,b,c,d,M,s,t) \
|
||||
a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define GG(a,b,c,d,M,s,t) \
|
||||
a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define HH(a,b,c,d,M,s,t) \
|
||||
a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define II(a,b,c,d,M,s,t) \
|
||||
a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _md5_compress(hash_state *md, unsigned char *buf)
|
||||
#else
|
||||
static int md5_compress(hash_state *md, unsigned char *buf)
|
||||
#endif
|
||||
{
|
||||
ulong32 i, W[16], a, b, c, d;
|
||||
#ifdef LTC_SMALL_CODE
|
||||
ulong32 t;
|
||||
#endif
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32L(W[i], buf + (4*i));
|
||||
}
|
||||
|
||||
/* copy state */
|
||||
a = md->md5.state[0];
|
||||
b = md->md5.state[1];
|
||||
c = md->md5.state[2];
|
||||
d = md->md5.state[3];
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 32; ++i) {
|
||||
GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 48; ++i) {
|
||||
HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 64; ++i) {
|
||||
II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
#else
|
||||
FF(a,b,c,d,W[0],7,0xd76aa478UL)
|
||||
FF(d,a,b,c,W[1],12,0xe8c7b756UL)
|
||||
FF(c,d,a,b,W[2],17,0x242070dbUL)
|
||||
FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
|
||||
FF(a,b,c,d,W[4],7,0xf57c0fafUL)
|
||||
FF(d,a,b,c,W[5],12,0x4787c62aUL)
|
||||
FF(c,d,a,b,W[6],17,0xa8304613UL)
|
||||
FF(b,c,d,a,W[7],22,0xfd469501UL)
|
||||
FF(a,b,c,d,W[8],7,0x698098d8UL)
|
||||
FF(d,a,b,c,W[9],12,0x8b44f7afUL)
|
||||
FF(c,d,a,b,W[10],17,0xffff5bb1UL)
|
||||
FF(b,c,d,a,W[11],22,0x895cd7beUL)
|
||||
FF(a,b,c,d,W[12],7,0x6b901122UL)
|
||||
FF(d,a,b,c,W[13],12,0xfd987193UL)
|
||||
FF(c,d,a,b,W[14],17,0xa679438eUL)
|
||||
FF(b,c,d,a,W[15],22,0x49b40821UL)
|
||||
GG(a,b,c,d,W[1],5,0xf61e2562UL)
|
||||
GG(d,a,b,c,W[6],9,0xc040b340UL)
|
||||
GG(c,d,a,b,W[11],14,0x265e5a51UL)
|
||||
GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
|
||||
GG(a,b,c,d,W[5],5,0xd62f105dUL)
|
||||
GG(d,a,b,c,W[10],9,0x02441453UL)
|
||||
GG(c,d,a,b,W[15],14,0xd8a1e681UL)
|
||||
GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
|
||||
GG(a,b,c,d,W[9],5,0x21e1cde6UL)
|
||||
GG(d,a,b,c,W[14],9,0xc33707d6UL)
|
||||
GG(c,d,a,b,W[3],14,0xf4d50d87UL)
|
||||
GG(b,c,d,a,W[8],20,0x455a14edUL)
|
||||
GG(a,b,c,d,W[13],5,0xa9e3e905UL)
|
||||
GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
|
||||
GG(c,d,a,b,W[7],14,0x676f02d9UL)
|
||||
GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
|
||||
HH(a,b,c,d,W[5],4,0xfffa3942UL)
|
||||
HH(d,a,b,c,W[8],11,0x8771f681UL)
|
||||
HH(c,d,a,b,W[11],16,0x6d9d6122UL)
|
||||
HH(b,c,d,a,W[14],23,0xfde5380cUL)
|
||||
HH(a,b,c,d,W[1],4,0xa4beea44UL)
|
||||
HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
|
||||
HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
|
||||
HH(b,c,d,a,W[10],23,0xbebfbc70UL)
|
||||
HH(a,b,c,d,W[13],4,0x289b7ec6UL)
|
||||
HH(d,a,b,c,W[0],11,0xeaa127faUL)
|
||||
HH(c,d,a,b,W[3],16,0xd4ef3085UL)
|
||||
HH(b,c,d,a,W[6],23,0x04881d05UL)
|
||||
HH(a,b,c,d,W[9],4,0xd9d4d039UL)
|
||||
HH(d,a,b,c,W[12],11,0xe6db99e5UL)
|
||||
HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
|
||||
HH(b,c,d,a,W[2],23,0xc4ac5665UL)
|
||||
II(a,b,c,d,W[0],6,0xf4292244UL)
|
||||
II(d,a,b,c,W[7],10,0x432aff97UL)
|
||||
II(c,d,a,b,W[14],15,0xab9423a7UL)
|
||||
II(b,c,d,a,W[5],21,0xfc93a039UL)
|
||||
II(a,b,c,d,W[12],6,0x655b59c3UL)
|
||||
II(d,a,b,c,W[3],10,0x8f0ccc92UL)
|
||||
II(c,d,a,b,W[10],15,0xffeff47dUL)
|
||||
II(b,c,d,a,W[1],21,0x85845dd1UL)
|
||||
II(a,b,c,d,W[8],6,0x6fa87e4fUL)
|
||||
II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
|
||||
II(c,d,a,b,W[6],15,0xa3014314UL)
|
||||
II(b,c,d,a,W[13],21,0x4e0811a1UL)
|
||||
II(a,b,c,d,W[4],6,0xf7537e82UL)
|
||||
II(d,a,b,c,W[11],10,0xbd3af235UL)
|
||||
II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
|
||||
II(b,c,d,a,W[9],21,0xeb86d391UL)
|
||||
#endif
|
||||
|
||||
md->md5.state[0] = md->md5.state[0] + a;
|
||||
md->md5.state[1] = md->md5.state[1] + b;
|
||||
md->md5.state[2] = md->md5.state[2] + c;
|
||||
md->md5.state[3] = md->md5.state[3] + d;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int md5_compress(hash_state *md, unsigned char *buf)
|
||||
{
|
||||
int err;
|
||||
err = _md5_compress(md, buf);
|
||||
burn_stack(sizeof(ulong32) * 21);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the hash state
|
||||
@param md The hash state you wish to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int md5_init(hash_state * md)
|
||||
{
|
||||
LTC_ARGCHK(md != NULL);
|
||||
md->md5.state[0] = 0x67452301UL;
|
||||
md->md5.state[1] = 0xefcdab89UL;
|
||||
md->md5.state[2] = 0x98badcfeUL;
|
||||
md->md5.state[3] = 0x10325476UL;
|
||||
md->md5.curlen = 0;
|
||||
md->md5.length = 0;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
HASH_PROCESS(md5_process, md5_compress, md5, 64)
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (16 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int md5_done(hash_state * md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(md != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (md->md5.curlen >= sizeof(md->md5.buf)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
/* increase the length of the message */
|
||||
md->md5.length += md->md5.curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->md5.curlen > 56) {
|
||||
while (md->md5.curlen < 64) {
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
|
||||
}
|
||||
md5_compress(md, md->md5.buf);
|
||||
md->md5.curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->md5.curlen < 56) {
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64L(md->md5.length, md->md5.buf+56);
|
||||
md5_compress(md, md->md5.buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 4; i++) {
|
||||
STORE32L(md->md5.state[i], out+(4*i));
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Self-test the hash
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int md5_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
char *msg;
|
||||
unsigned char hash[16];
|
||||
} tests[] = {
|
||||
{ "",
|
||||
{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
|
||||
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
|
||||
{ "a",
|
||||
{0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
|
||||
0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
|
||||
{ "abc",
|
||||
{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
|
||||
0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
|
||||
{ "message digest",
|
||||
{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
|
||||
0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
|
||||
0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
|
||||
0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
|
||||
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
|
||||
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
|
||||
{ NULL, { 0 } }
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[16];
|
||||
hash_state md;
|
||||
|
||||
for (i = 0; tests[i].msg != NULL; i++) {
|
||||
md5_init(&md);
|
||||
md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
|
||||
md5_done(&md, tmp);
|
||||
if (XMEMCMP(tmp, tests[i].hash, 16) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */
|
||||
/* $Revision: 1.10 $ */
|
||||
/* $Date: 2007/05/12 14:25:28 $ */
|
||||
288
vendor/stormlib-9/src/libtomcrypt/src/hashes/sha1.c
vendored
Normal file
288
vendor/stormlib-9/src/libtomcrypt/src/hashes/sha1.c
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file sha1.c
|
||||
LTC_SHA1 code by Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
|
||||
const struct ltc_hash_descriptor sha1_desc =
|
||||
{
|
||||
"sha1",
|
||||
2,
|
||||
20,
|
||||
64,
|
||||
|
||||
/* OID */
|
||||
{ 1, 3, 14, 3, 2, 26, },
|
||||
6,
|
||||
|
||||
&sha1_init,
|
||||
&sha1_process,
|
||||
&sha1_done,
|
||||
&sha1_test,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define F0(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define F1(x,y,z) (x ^ y ^ z)
|
||||
#define F2(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define F3(x,y,z) (x ^ y ^ z)
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _sha1_compress(hash_state *md, unsigned char *buf)
|
||||
#else
|
||||
static int sha1_compress(hash_state *md, unsigned char *buf)
|
||||
#endif
|
||||
{
|
||||
ulong32 a,b,c,d,e,W[80],i;
|
||||
#ifdef LTC_SMALL_CODE
|
||||
ulong32 t;
|
||||
#endif
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32H(W[i], buf + (4*i));
|
||||
}
|
||||
|
||||
/* copy state */
|
||||
a = md->sha1.state[0];
|
||||
b = md->sha1.state[1];
|
||||
c = md->sha1.state[2];
|
||||
d = md->sha1.state[3];
|
||||
e = md->sha1.state[4];
|
||||
|
||||
/* expand it */
|
||||
for (i = 16; i < 80; i++) {
|
||||
W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
|
||||
}
|
||||
|
||||
/* compress */
|
||||
/* round one */
|
||||
#define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
|
||||
#define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
|
||||
#define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
|
||||
#define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
|
||||
for (i = 0; i < 20; ) {
|
||||
FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 40; ) {
|
||||
FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 60; ) {
|
||||
FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 80; ) {
|
||||
FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (i = 0; i < 20; ) {
|
||||
FF0(a,b,c,d,e,i++);
|
||||
FF0(e,a,b,c,d,i++);
|
||||
FF0(d,e,a,b,c,i++);
|
||||
FF0(c,d,e,a,b,i++);
|
||||
FF0(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round two */
|
||||
for (; i < 40; ) {
|
||||
FF1(a,b,c,d,e,i++);
|
||||
FF1(e,a,b,c,d,i++);
|
||||
FF1(d,e,a,b,c,i++);
|
||||
FF1(c,d,e,a,b,i++);
|
||||
FF1(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round three */
|
||||
for (; i < 60; ) {
|
||||
FF2(a,b,c,d,e,i++);
|
||||
FF2(e,a,b,c,d,i++);
|
||||
FF2(d,e,a,b,c,i++);
|
||||
FF2(c,d,e,a,b,i++);
|
||||
FF2(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round four */
|
||||
for (; i < 80; ) {
|
||||
FF3(a,b,c,d,e,i++);
|
||||
FF3(e,a,b,c,d,i++);
|
||||
FF3(d,e,a,b,c,i++);
|
||||
FF3(c,d,e,a,b,i++);
|
||||
FF3(b,c,d,e,a,i++);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef FF0
|
||||
#undef FF1
|
||||
#undef FF2
|
||||
#undef FF3
|
||||
|
||||
/* store */
|
||||
md->sha1.state[0] = md->sha1.state[0] + a;
|
||||
md->sha1.state[1] = md->sha1.state[1] + b;
|
||||
md->sha1.state[2] = md->sha1.state[2] + c;
|
||||
md->sha1.state[3] = md->sha1.state[3] + d;
|
||||
md->sha1.state[4] = md->sha1.state[4] + e;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int sha1_compress(hash_state *md, unsigned char *buf)
|
||||
{
|
||||
int err;
|
||||
err = _sha1_compress(md, buf);
|
||||
burn_stack(sizeof(ulong32) * 87);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the hash state
|
||||
@param md The hash state you wish to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha1_init(hash_state * md)
|
||||
{
|
||||
LTC_ARGCHK(md != NULL);
|
||||
md->sha1.state[0] = 0x67452301UL;
|
||||
md->sha1.state[1] = 0xefcdab89UL;
|
||||
md->sha1.state[2] = 0x98badcfeUL;
|
||||
md->sha1.state[3] = 0x10325476UL;
|
||||
md->sha1.state[4] = 0xc3d2e1f0UL;
|
||||
md->sha1.curlen = 0;
|
||||
md->sha1.length = 0;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (20 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha1_done(hash_state * md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(md != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* increase the length of the message */
|
||||
md->sha1.length += md->sha1.curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->sha1.curlen > 56) {
|
||||
while (md->sha1.curlen < 64) {
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
|
||||
}
|
||||
sha1_compress(md, md->sha1.buf);
|
||||
md->sha1.curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->sha1.curlen < 56) {
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->sha1.length, md->sha1.buf+56);
|
||||
sha1_compress(md, md->sha1.buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 5; i++) {
|
||||
STORE32H(md->sha1.state[i], out+(4*i));
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Self-test the hash
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int sha1_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
char *msg;
|
||||
unsigned char hash[20];
|
||||
} tests[] = {
|
||||
{ "abc",
|
||||
{ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
|
||||
0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
|
||||
0x9c, 0xd0, 0xd8, 0x9d }
|
||||
},
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
|
||||
0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
|
||||
0xE5, 0x46, 0x70, 0xF1 }
|
||||
}
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[20];
|
||||
hash_state md;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
|
||||
sha1_init(&md);
|
||||
sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
|
||||
sha1_done(&md, tmp);
|
||||
if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */
|
||||
/* $Revision: 1.10 $ */
|
||||
/* $Date: 2007/05/12 14:25:28 $ */
|
||||
340
vendor/stormlib-9/src/libtomcrypt/src/hashes/sha256.c
vendored
Normal file
340
vendor/stormlib-9/src/libtomcrypt/src/hashes/sha256.c
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file sha256.c
|
||||
LTC_SHA256 by Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_SHA256
|
||||
|
||||
const struct ltc_hash_descriptor sha256_desc =
|
||||
{
|
||||
"sha256",
|
||||
0,
|
||||
32,
|
||||
64,
|
||||
|
||||
/* OID */
|
||||
{ 2, 16, 840, 1, 101, 3, 4, 2, 1, },
|
||||
9,
|
||||
|
||||
&sha256_init,
|
||||
&sha256_process,
|
||||
&sha256_done,
|
||||
&sha256_test,
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
/* the K array */
|
||||
static const ulong32 K[64] = {
|
||||
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
|
||||
0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
|
||||
0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
|
||||
0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
|
||||
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
|
||||
0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
|
||||
0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
|
||||
0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
|
||||
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
|
||||
0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
|
||||
0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
|
||||
0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
|
||||
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Various logical functions */
|
||||
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) RORc((x),(n))
|
||||
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
|
||||
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
|
||||
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
|
||||
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
|
||||
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
|
||||
|
||||
/* compress 512-bits */
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _sha256_compress(hash_state * md, unsigned char *buf)
|
||||
#else
|
||||
static int sha256_compress(hash_state * md, unsigned char *buf)
|
||||
#endif
|
||||
{
|
||||
ulong32 S[8], W[64], t0, t1;
|
||||
#ifdef LTC_SMALL_CODE
|
||||
ulong32 t;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
/* copy state into S */
|
||||
for (i = 0; i < 8; i++) {
|
||||
S[i] = md->sha256.state[i];
|
||||
}
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32H(W[i], buf + (4*i));
|
||||
}
|
||||
|
||||
/* fill W[16..63] */
|
||||
for (i = 16; i < 64; i++) {
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
#ifdef LTC_SMALL_CODE
|
||||
#define RND(a,b,c,d,e,f,g,h,i) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
|
||||
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
|
||||
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
|
||||
}
|
||||
#else
|
||||
#define RND(a,b,c,d,e,f,g,h,i,ki) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
|
||||
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
|
||||
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
|
||||
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
|
||||
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
|
||||
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
|
||||
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
|
||||
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
|
||||
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
|
||||
|
||||
#undef RND
|
||||
|
||||
#endif
|
||||
|
||||
/* feedback */
|
||||
for (i = 0; i < 8; i++) {
|
||||
md->sha256.state[i] = md->sha256.state[i] + S[i];
|
||||
}
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int sha256_compress(hash_state * md, unsigned char *buf)
|
||||
{
|
||||
int err;
|
||||
err = _sha256_compress(md, buf);
|
||||
burn_stack(sizeof(ulong32) * 74);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the hash state
|
||||
@param md The hash state you wish to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha256_init(hash_state * md)
|
||||
{
|
||||
LTC_ARGCHK(md != NULL);
|
||||
|
||||
md->sha256.curlen = 0;
|
||||
md->sha256.length = 0;
|
||||
md->sha256.state[0] = 0x6A09E667UL;
|
||||
md->sha256.state[1] = 0xBB67AE85UL;
|
||||
md->sha256.state[2] = 0x3C6EF372UL;
|
||||
md->sha256.state[3] = 0xA54FF53AUL;
|
||||
md->sha256.state[4] = 0x510E527FUL;
|
||||
md->sha256.state[5] = 0x9B05688CUL;
|
||||
md->sha256.state[6] = 0x1F83D9ABUL;
|
||||
md->sha256.state[7] = 0x5BE0CD19UL;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (32 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha256_done(hash_state * md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(md != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
/* increase the length of the message */
|
||||
md->sha256.length += md->sha256.curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->sha256.curlen > 56) {
|
||||
while (md->sha256.curlen < 64) {
|
||||
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
|
||||
}
|
||||
sha256_compress(md, md->sha256.buf);
|
||||
md->sha256.curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->sha256.curlen < 56) {
|
||||
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->sha256.length, md->sha256.buf+56);
|
||||
sha256_compress(md, md->sha256.buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 8; i++) {
|
||||
STORE32H(md->sha256.state[i], out+(4*i));
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Self-test the hash
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int sha256_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
char *msg;
|
||||
unsigned char hash[32];
|
||||
} tests[] = {
|
||||
{ "abc",
|
||||
{ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
|
||||
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
|
||||
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
|
||||
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
|
||||
},
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
{ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
|
||||
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
|
||||
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
|
||||
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
|
||||
},
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[32];
|
||||
hash_state md;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
|
||||
sha256_init(&md);
|
||||
sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
|
||||
sha256_done(&md, tmp);
|
||||
if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LTC_SHA224
|
||||
#include "sha224.c"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */
|
||||
/* $Revision: 1.11 $ */
|
||||
/* $Date: 2007/05/12 14:25:28 $ */
|
||||
91
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt.h
vendored
Normal file
91
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt.h
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef TOMCRYPT_H_
|
||||
#define TOMCRYPT_H_
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* use configuration data */
|
||||
#include "tomcrypt_custom.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* version */
|
||||
#define CRYPT 0x0117
|
||||
#define SCRYPT "1.17"
|
||||
|
||||
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
|
||||
#define MAXBLOCKSIZE 128
|
||||
|
||||
/* descriptor table size */
|
||||
#define TAB_SIZE 32
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4333) // der_encode_utf8_string.c(91) : warning C4333: '>>' : right shift by too large amount, data loss
|
||||
#endif
|
||||
|
||||
/* error codes [will be expanded in future releases] */
|
||||
enum {
|
||||
CRYPT_OK=0, /* Result OK */
|
||||
CRYPT_ERROR, /* Generic Error */
|
||||
CRYPT_NOP, /* Not a failure but no operation was performed */
|
||||
|
||||
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
|
||||
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
|
||||
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
|
||||
|
||||
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
|
||||
CRYPT_INVALID_PACKET, /* Invalid input packet given */
|
||||
|
||||
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
|
||||
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
|
||||
|
||||
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
|
||||
CRYPT_INVALID_HASH, /* Invalid hash specified */
|
||||
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
|
||||
|
||||
CRYPT_MEM, /* Out of memory */
|
||||
|
||||
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
|
||||
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
|
||||
|
||||
CRYPT_INVALID_ARG, /* Generic invalid argument */
|
||||
CRYPT_FILE_NOTFOUND, /* File Not Found */
|
||||
|
||||
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
|
||||
CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
|
||||
CRYPT_PK_DUP, /* Duplicate key already in key ring */
|
||||
CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
|
||||
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
|
||||
|
||||
CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
|
||||
CRYPT_PK_INVALID_PADDING /* Invalid padding on input */
|
||||
};
|
||||
|
||||
#include "tomcrypt_cfg.h"
|
||||
#include "tomcrypt_macros.h"
|
||||
#include "tomcrypt_cipher.h"
|
||||
#include "tomcrypt_hash.h"
|
||||
#include "tomcrypt_mac.h"
|
||||
#include "tomcrypt_prng.h"
|
||||
#include "tomcrypt_pk.h"
|
||||
#include "tomcrypt_math.h"
|
||||
#include "tomcrypt_misc.h"
|
||||
#include "tomcrypt_argchk.h"
|
||||
#include "tomcrypt_pkcs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TOMCRYPT_H_ */
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */
|
||||
/* $Revision: 1.21 $ */
|
||||
/* $Date: 2006/12/16 19:34:05 $ */
|
||||
38
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_argchk.h
vendored
Normal file
38
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_argchk.h
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/* Defines the LTC_ARGCHK macro used within the library */
|
||||
/* ARGTYPE is defined in mycrypt_cfg.h */
|
||||
#if ARGTYPE == 0
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/* this is the default LibTomCrypt macro */
|
||||
void crypt_argchk(char *v, char *s, int d);
|
||||
#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 1
|
||||
|
||||
/* fatal type of error */
|
||||
#define LTC_ARGCHK(x) assert((x))
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 2
|
||||
|
||||
#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 3
|
||||
|
||||
#define LTC_ARGCHK(x)
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 4
|
||||
|
||||
#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
|
||||
#define LTC_ARGCHKVD(x) if (!(x)) return;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2006/08/27 20:50:21 $ */
|
||||
144
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_cfg.h
vendored
Normal file
144
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_cfg.h
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/* This is the build config file.
|
||||
*
|
||||
* With this you can setup what to inlcude/exclude automatically during any build. Just comment
|
||||
* out the line that #define's the word for the thing you want to remove. phew!
|
||||
*/
|
||||
|
||||
#ifndef TOMCRYPT_CFG_H
|
||||
#define TOMCRYPT_CFG_H
|
||||
|
||||
#if defined(_WIN32) || defined(_MSC_VER)
|
||||
#define LTC_CALL __cdecl
|
||||
#else
|
||||
#ifndef LTC_CALL
|
||||
#define LTC_CALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LTC_EXPORT
|
||||
#define LTC_EXPORT
|
||||
#endif
|
||||
|
||||
/* certain platforms use macros for these, making the prototypes broken */
|
||||
#ifndef LTC_NO_PROTOTYPES
|
||||
|
||||
/* you can change how memory allocation works ... */
|
||||
LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
|
||||
LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
|
||||
LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
|
||||
LTC_EXPORT void LTC_CALL XFREE(void *p);
|
||||
|
||||
LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(LTC_CALL * compar)(const void *, const void *));
|
||||
|
||||
/* change the clock function too */
|
||||
LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
|
||||
#endif // LTC_NO_PROTOTYPES
|
||||
|
||||
/* various other functions */
|
||||
#ifndef LTC_NO_PROTOTYPES_MEMCPY
|
||||
LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
|
||||
#endif
|
||||
|
||||
#ifndef LTC_NO_PROTOTYPES_MEMCMP
|
||||
LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
|
||||
#endif
|
||||
|
||||
#ifndef LTC_NO_PROTOTYPES_MEMSET
|
||||
LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
|
||||
#endif
|
||||
|
||||
#ifndef LTC_NO_PROTOTYPES_STRCMP
|
||||
LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
|
||||
#endif
|
||||
|
||||
/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
|
||||
#ifndef ARGTYPE
|
||||
#define ARGTYPE 0
|
||||
#endif
|
||||
|
||||
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
|
||||
*
|
||||
* Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
|
||||
* The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
|
||||
* use the portable [slower] macros.
|
||||
*/
|
||||
|
||||
/* detect x86-32 machines somewhat */
|
||||
#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))))
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_32BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detects MIPS R5900 processors (PS2) */
|
||||
#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_64BITWORD
|
||||
#endif
|
||||
|
||||
/* detect amd64 */
|
||||
#if !defined(__STRICT_ANSI__) && defined(__x86_64__)
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_64BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detect PPC32 */
|
||||
#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
|
||||
#define ENDIAN_BIG
|
||||
#define ENDIAN_32BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detect sparc and sparc64 */
|
||||
#if defined(__sparc__)
|
||||
#define ENDIAN_BIG
|
||||
#if defined(__arch64__)
|
||||
#define ENDIAN_64BITWORD
|
||||
#else
|
||||
#define ENDIAN_32BITWORD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_NO_FAST
|
||||
#ifdef LTC_FAST
|
||||
#undef LTC_FAST
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* No asm is a quick way to disable anything "not portable" */
|
||||
#ifdef LTC_NO_ASM
|
||||
#undef ENDIAN_LITTLE
|
||||
#undef ENDIAN_BIG
|
||||
#undef ENDIAN_32BITWORD
|
||||
#undef ENDIAN_64BITWORD
|
||||
#undef LTC_FAST
|
||||
#undef LTC_FAST_TYPE
|
||||
#define LTC_NO_ROLC
|
||||
#define LTC_NO_BSWAP
|
||||
#endif
|
||||
|
||||
/* #define ENDIAN_LITTLE */
|
||||
/* #define ENDIAN_BIG */
|
||||
|
||||
/* #define ENDIAN_32BITWORD */
|
||||
/* #define ENDIAN_64BITWORD */
|
||||
|
||||
#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
|
||||
#error You must specify a word size as well as endianess in tomcrypt_cfg.h
|
||||
#endif
|
||||
|
||||
#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
|
||||
#define ENDIAN_NEUTRAL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */
|
||||
/* $Revision: 1.19 $ */
|
||||
/* $Date: 2006/12/04 02:19:48 $ */
|
||||
891
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_cipher.h
vendored
Normal file
891
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_cipher.h
vendored
Normal file
@ -0,0 +1,891 @@
|
||||
/* ---- SYMMETRIC KEY STUFF -----
|
||||
*
|
||||
* We put each of the ciphers scheduled keys in their own structs then we put all of
|
||||
* the key formats in one union. This makes the function prototypes easier to use.
|
||||
*/
|
||||
#ifdef LTC_BLOWFISH
|
||||
struct blowfish_key {
|
||||
ulong32 S[4][256];
|
||||
ulong32 K[18];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC5
|
||||
struct rc5_key {
|
||||
int rounds;
|
||||
ulong32 K[50];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC6
|
||||
struct rc6_key {
|
||||
ulong32 K[44];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFERP
|
||||
struct saferp_key {
|
||||
unsigned char K[33][16];
|
||||
long rounds;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIJNDAEL
|
||||
struct rijndael_key {
|
||||
ulong32 eK[60], dK[60];
|
||||
int Nr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KSEED
|
||||
struct kseed_key {
|
||||
ulong32 K[32], dK[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KASUMI
|
||||
struct kasumi_key {
|
||||
ulong32 KLi1[8], KLi2[8],
|
||||
KOi1[8], KOi2[8], KOi3[8],
|
||||
KIi1[8], KIi2[8], KIi3[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTEA
|
||||
struct xtea_key {
|
||||
unsigned long A[32], B[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TWOFISH
|
||||
#ifndef LTC_TWOFISH_SMALL
|
||||
struct twofish_key {
|
||||
ulong32 S[4][256], K[40];
|
||||
};
|
||||
#else
|
||||
struct twofish_key {
|
||||
ulong32 K[40];
|
||||
unsigned char S[32], start;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFER
|
||||
#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6
|
||||
#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10
|
||||
#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8
|
||||
#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10
|
||||
#define LTC_SAFER_MAX_NOF_ROUNDS 13
|
||||
#define LTC_SAFER_BLOCK_LEN 8
|
||||
#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))
|
||||
typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN];
|
||||
typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN];
|
||||
struct safer_key { safer_key_t key; };
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC2
|
||||
struct rc2_key { unsigned xkey[64]; };
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DES
|
||||
struct des_key {
|
||||
ulong32 ek[32], dk[32];
|
||||
};
|
||||
|
||||
struct des3_key {
|
||||
ulong32 ek[3][32], dk[3][32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CAST5
|
||||
struct cast5_key {
|
||||
ulong32 K[32], keylen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_NOEKEON
|
||||
struct noekeon_key {
|
||||
ulong32 K[4], dK[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SKIPJACK
|
||||
struct skipjack_key {
|
||||
unsigned char key[10];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KHAZAD
|
||||
struct khazad_key {
|
||||
ulong64 roundKeyEnc[8 + 1];
|
||||
ulong64 roundKeyDec[8 + 1];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ANUBIS
|
||||
struct anubis_key {
|
||||
int keyBits;
|
||||
int R;
|
||||
ulong32 roundKeyEnc[18 + 1][4];
|
||||
ulong32 roundKeyDec[18 + 1][4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MULTI2
|
||||
struct multi2_key {
|
||||
int N;
|
||||
ulong32 uk[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Symmetric_key {
|
||||
#ifdef LTC_DES
|
||||
struct des_key des;
|
||||
struct des3_key des3;
|
||||
#endif
|
||||
#ifdef LTC_RC2
|
||||
struct rc2_key rc2;
|
||||
#endif
|
||||
#ifdef LTC_SAFER
|
||||
struct safer_key safer;
|
||||
#endif
|
||||
#ifdef LTC_TWOFISH
|
||||
struct twofish_key twofish;
|
||||
#endif
|
||||
#ifdef LTC_BLOWFISH
|
||||
struct blowfish_key blowfish;
|
||||
#endif
|
||||
#ifdef LTC_RC5
|
||||
struct rc5_key rc5;
|
||||
#endif
|
||||
#ifdef LTC_RC6
|
||||
struct rc6_key rc6;
|
||||
#endif
|
||||
#ifdef LTC_SAFERP
|
||||
struct saferp_key saferp;
|
||||
#endif
|
||||
#ifdef LTC_RIJNDAEL
|
||||
struct rijndael_key rijndael;
|
||||
#endif
|
||||
#ifdef LTC_XTEA
|
||||
struct xtea_key xtea;
|
||||
#endif
|
||||
#ifdef LTC_CAST5
|
||||
struct cast5_key cast5;
|
||||
#endif
|
||||
#ifdef LTC_NOEKEON
|
||||
struct noekeon_key noekeon;
|
||||
#endif
|
||||
#ifdef LTC_SKIPJACK
|
||||
struct skipjack_key skipjack;
|
||||
#endif
|
||||
#ifdef LTC_KHAZAD
|
||||
struct khazad_key khazad;
|
||||
#endif
|
||||
#ifdef LTC_ANUBIS
|
||||
struct anubis_key anubis;
|
||||
#endif
|
||||
#ifdef LTC_KSEED
|
||||
struct kseed_key kseed;
|
||||
#endif
|
||||
#ifdef LTC_KASUMI
|
||||
struct kasumi_key kasumi;
|
||||
#endif
|
||||
#ifdef LTC_MULTI2
|
||||
struct multi2_key multi2;
|
||||
#endif
|
||||
void *data;
|
||||
} symmetric_key;
|
||||
|
||||
#ifdef LTC_ECB_MODE
|
||||
/** A block cipher ECB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen;
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_ECB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CFB_MODE
|
||||
/** A block cipher CFB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE],
|
||||
/** The pad used to encrypt/decrypt */
|
||||
pad[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CFB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OFB_MODE
|
||||
/** A block cipher OFB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_OFB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CBC_MODE
|
||||
/** A block cipher CBC structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CBC;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_CTR_MODE
|
||||
/** A block cipher CTR structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen,
|
||||
/** The mode (endianess) of the CTR, 0==little, 1==big */
|
||||
mode,
|
||||
/** counter width */
|
||||
ctrlen;
|
||||
|
||||
/** The counter */
|
||||
unsigned char ctr[MAXBLOCKSIZE],
|
||||
/** The pad used to encrypt/decrypt */
|
||||
pad[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CTR;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_LRW_MODE
|
||||
/** A LRW structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen (must be a 128-bit block cipher) */
|
||||
int cipher;
|
||||
|
||||
/** The current IV */
|
||||
unsigned char IV[16],
|
||||
|
||||
/** the tweak key */
|
||||
tweak[16],
|
||||
|
||||
/** The current pad, it's the product of the first 15 bytes against the tweak key */
|
||||
pad[16];
|
||||
|
||||
/** The scheduled symmetric key */
|
||||
symmetric_key key;
|
||||
|
||||
#ifdef LRW_TABLES
|
||||
/** The pre-computed multiplication table */
|
||||
unsigned char PC[16][256][16];
|
||||
#endif
|
||||
} symmetric_LRW;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F8_MODE
|
||||
/** A block cipher F8 structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE],
|
||||
MIV[MAXBLOCKSIZE];
|
||||
/** Current block count */
|
||||
ulong32 blockcnt;
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_F8;
|
||||
#endif
|
||||
|
||||
|
||||
/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */
|
||||
extern struct ltc_cipher_descriptor {
|
||||
/** name of cipher */
|
||||
char *name;
|
||||
/** internal ID */
|
||||
unsigned char ID;
|
||||
/** min keysize (octets) */
|
||||
int min_key_length,
|
||||
/** max keysize (octets) */
|
||||
max_key_length,
|
||||
/** block size (octets) */
|
||||
block_length,
|
||||
/** default number of rounds */
|
||||
default_rounds;
|
||||
/** Setup the cipher
|
||||
@param key The input symmetric key
|
||||
@param keylen The length of the input key (octets)
|
||||
@param num_rounds The requested number of rounds (0==default)
|
||||
@param skey [out] The destination of the scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
/** Encrypt a block
|
||||
@param pt The plaintext
|
||||
@param ct [out] The ciphertext
|
||||
@param skey The scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
/** Decrypt a block
|
||||
@param ct The ciphertext
|
||||
@param pt [out] The plaintext
|
||||
@param skey The scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
/** Test the block cipher
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
|
||||
/** Terminate the context
|
||||
@param skey The scheduled key
|
||||
*/
|
||||
void (*done)(symmetric_key *skey);
|
||||
|
||||
/** Determine a key size
|
||||
@param keysize [in/out] The size of the key desired and the suggested size
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*keysize)(int *keysize);
|
||||
|
||||
/** Accelerators **/
|
||||
/** Accelerated ECB encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
|
||||
|
||||
/** Accelerated ECB decryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CBC encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CBC decryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CTR encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param mode little or big endian counter (mode=0 or mode=1)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
|
||||
|
||||
/** Accelerated LRW
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param tweak The LRW tweak
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
|
||||
|
||||
/** Accelerated LRW
|
||||
@param ct Ciphertext
|
||||
@param pt Plaintext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param tweak The LRW tweak
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CCM packet (one-shot)
|
||||
@param key The secret key to use
|
||||
@param keylen The length of the secret key (octets)
|
||||
@param uskey A previously scheduled key [optional can be NULL]
|
||||
@param nonce The session nonce [use once]
|
||||
@param noncelen The length of the nonce
|
||||
@param header The header for the session
|
||||
@param headerlen The length of the header (octets)
|
||||
@param pt [out] The plaintext
|
||||
@param ptlen The length of the plaintext (octets)
|
||||
@param ct [out] The ciphertext
|
||||
@param tag [out] The destination tag
|
||||
@param taglen [in/out] The max size and resulting size of the authentication tag
|
||||
@param direction Encrypt or Decrypt direction (0 or 1)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ccm_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
symmetric_key *uskey,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
/** Accelerated GCM packet (one shot)
|
||||
@param key The secret key
|
||||
@param keylen The length of the secret key
|
||||
@param IV The initial vector
|
||||
@param IVlen The length of the initial vector
|
||||
@param adata The additional authentication data (header)
|
||||
@param adatalen The length of the adata
|
||||
@param pt The plaintext
|
||||
@param ptlen The length of the plaintext (ciphertext length is the same)
|
||||
@param ct The ciphertext
|
||||
@param tag [out] The MAC tag
|
||||
@param taglen [in/out] The MAC tag length
|
||||
@param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*accel_gcm_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
/** Accelerated one shot LTC_OMAC
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*omac_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/** Accelerated one shot XCBC
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*xcbc_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/** Accelerated one shot F9
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
@remark Requires manual padding
|
||||
*/
|
||||
int (*f9_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
} cipher_descriptor[];
|
||||
|
||||
#ifdef LTC_BLOWFISH
|
||||
int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int blowfish_test(void);
|
||||
void blowfish_done(symmetric_key *skey);
|
||||
int blowfish_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor blowfish_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC5
|
||||
int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc5_test(void);
|
||||
void rc5_done(symmetric_key *skey);
|
||||
int rc5_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC6
|
||||
int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc6_test(void);
|
||||
void rc6_done(symmetric_key *skey);
|
||||
int rc6_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc6_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC2
|
||||
int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc2_test(void);
|
||||
void rc2_done(symmetric_key *skey);
|
||||
int rc2_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFERP
|
||||
int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int saferp_test(void);
|
||||
void saferp_done(symmetric_key *skey);
|
||||
int saferp_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor saferp_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFER
|
||||
int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
|
||||
int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
|
||||
int safer_k64_test(void);
|
||||
int safer_sk64_test(void);
|
||||
int safer_sk128_test(void);
|
||||
void safer_done(symmetric_key *skey);
|
||||
int safer_64_keysize(int *keysize);
|
||||
int safer_128_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIJNDAEL
|
||||
|
||||
/* make aes an alias */
|
||||
#define aes_setup rijndael_setup
|
||||
#define aes_ecb_encrypt rijndael_ecb_encrypt
|
||||
#define aes_ecb_decrypt rijndael_ecb_decrypt
|
||||
#define aes_test rijndael_test
|
||||
#define aes_done rijndael_done
|
||||
#define aes_keysize rijndael_keysize
|
||||
|
||||
#define aes_enc_setup rijndael_enc_setup
|
||||
#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt
|
||||
#define aes_enc_keysize rijndael_enc_keysize
|
||||
|
||||
int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rijndael_test(void);
|
||||
void rijndael_done(symmetric_key *skey);
|
||||
int rijndael_keysize(int *keysize);
|
||||
int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
void rijndael_enc_done(symmetric_key *skey);
|
||||
int rijndael_enc_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
|
||||
extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTEA
|
||||
int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int xtea_test(void);
|
||||
void xtea_done(symmetric_key *skey);
|
||||
int xtea_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor xtea_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TWOFISH
|
||||
int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int twofish_test(void);
|
||||
void twofish_done(symmetric_key *skey);
|
||||
int twofish_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor twofish_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DES
|
||||
int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int des_test(void);
|
||||
void des_done(symmetric_key *skey);
|
||||
int des_keysize(int *keysize);
|
||||
int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int des3_test(void);
|
||||
void des3_done(symmetric_key *skey);
|
||||
int des3_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor des_desc, des3_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CAST5
|
||||
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int cast5_test(void);
|
||||
void cast5_done(symmetric_key *skey);
|
||||
int cast5_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor cast5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_NOEKEON
|
||||
int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int noekeon_test(void);
|
||||
void noekeon_done(symmetric_key *skey);
|
||||
int noekeon_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor noekeon_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SKIPJACK
|
||||
int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int skipjack_test(void);
|
||||
void skipjack_done(symmetric_key *skey);
|
||||
int skipjack_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor skipjack_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KHAZAD
|
||||
int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int khazad_test(void);
|
||||
void khazad_done(symmetric_key *skey);
|
||||
int khazad_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor khazad_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ANUBIS
|
||||
int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int anubis_test(void);
|
||||
void anubis_done(symmetric_key *skey);
|
||||
int anubis_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor anubis_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KSEED
|
||||
int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int kseed_test(void);
|
||||
void kseed_done(symmetric_key *skey);
|
||||
int kseed_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor kseed_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KASUMI
|
||||
int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int kasumi_test(void);
|
||||
void kasumi_done(symmetric_key *skey);
|
||||
int kasumi_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor kasumi_desc;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_MULTI2
|
||||
int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int multi2_test(void);
|
||||
void multi2_done(symmetric_key *skey);
|
||||
int multi2_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor multi2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ECB_MODE
|
||||
int ecb_start(int cipher, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_ECB *ecb);
|
||||
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
|
||||
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
|
||||
int ecb_done(symmetric_ECB *ecb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CFB_MODE
|
||||
int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_CFB *cfb);
|
||||
int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
|
||||
int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_done(symmetric_CFB *cfb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OFB_MODE
|
||||
int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_OFB *ofb);
|
||||
int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
|
||||
int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_done(symmetric_OFB *ofb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CBC_MODE
|
||||
int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_CBC *cbc);
|
||||
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
|
||||
int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_done(symmetric_CBC *cbc);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CTR_MODE
|
||||
|
||||
#define CTR_COUNTER_LITTLE_ENDIAN 0x0000
|
||||
#define CTR_COUNTER_BIG_ENDIAN 0x1000
|
||||
#define LTC_CTR_RFC3686 0x2000
|
||||
|
||||
int ctr_start( int cipher,
|
||||
const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
int num_rounds, int ctr_mode,
|
||||
symmetric_CTR *ctr);
|
||||
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
|
||||
int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_done(symmetric_CTR *ctr);
|
||||
int ctr_test(void);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_LRW_MODE
|
||||
|
||||
#define LRW_ENCRYPT 0
|
||||
#define LRW_DECRYPT 1
|
||||
|
||||
int lrw_start( int cipher,
|
||||
const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *tweak,
|
||||
int num_rounds,
|
||||
symmetric_LRW *lrw);
|
||||
int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
|
||||
int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_done(symmetric_LRW *lrw);
|
||||
int lrw_test(void);
|
||||
|
||||
/* don't call */
|
||||
int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F8_MODE
|
||||
int f8_start( int cipher, const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *salt_key, int skeylen,
|
||||
int num_rounds, symmetric_F8 *f8);
|
||||
int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8);
|
||||
int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_done(symmetric_F8 *f8);
|
||||
int f8_test_mode(void);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTS_MODE
|
||||
typedef struct {
|
||||
symmetric_key key1, key2;
|
||||
int cipher;
|
||||
} symmetric_xts;
|
||||
|
||||
int xts_start( int cipher,
|
||||
const unsigned char *key1,
|
||||
const unsigned char *key2,
|
||||
unsigned long keylen,
|
||||
int num_rounds,
|
||||
symmetric_xts *xts);
|
||||
|
||||
int xts_encrypt(
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
const unsigned char *tweak,
|
||||
symmetric_xts *xts);
|
||||
int xts_decrypt(
|
||||
const unsigned char *ct, unsigned long ptlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tweak,
|
||||
symmetric_xts *xts);
|
||||
|
||||
void xts_done(symmetric_xts *xts);
|
||||
int xts_test(void);
|
||||
void xts_mult_x(unsigned char *I);
|
||||
#endif
|
||||
|
||||
int find_cipher(const char *name);
|
||||
int find_cipher_any(const char *name, int blocklen, int keylen);
|
||||
int find_cipher_id(unsigned char ID);
|
||||
int register_cipher(const struct ltc_cipher_descriptor *cipher);
|
||||
int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
|
||||
int cipher_is_valid(int idx);
|
||||
|
||||
LTC_MUTEX_PROTO(ltc_cipher_mutex)
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */
|
||||
/* $Revision: 1.54 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
424
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h
vendored
Normal file
424
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h
vendored
Normal file
@ -0,0 +1,424 @@
|
||||
#ifndef TOMCRYPT_CUSTOM_H_
|
||||
#define TOMCRYPT_CUSTOM_H_
|
||||
|
||||
#define LTC_NO_CIPHERS
|
||||
#define LTC_NO_HASHES
|
||||
#define LTC_NO_MACS
|
||||
#define LTC_NO_PRNGS
|
||||
#define LTC_NO_CURVES
|
||||
#define LTC_NO_MODES
|
||||
#define LTC_NO_PKCS
|
||||
#define LTC_NO_ROLC
|
||||
|
||||
#define LTC_SOURCE
|
||||
#define LTC_SHA256
|
||||
#define LTC_SHA1
|
||||
#define LTC_MD5
|
||||
#define LTC_DER
|
||||
|
||||
#define LTM_DESC
|
||||
#define USE_LTM
|
||||
|
||||
/* macros for various libc functions you can change for embedded targets */
|
||||
#ifndef XMALLOC
|
||||
#ifdef malloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XMALLOC LibTomMalloc
|
||||
#endif
|
||||
#ifndef XREALLOC
|
||||
#ifdef realloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XREALLOC LibTomRealloc
|
||||
#endif
|
||||
#ifndef XCALLOC
|
||||
#ifdef calloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XCALLOC LibTomCalloc
|
||||
#endif
|
||||
#ifndef XFREE
|
||||
#ifdef free
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XFREE LibTomFree
|
||||
#endif
|
||||
|
||||
#ifndef XMEMSET
|
||||
#ifdef memset
|
||||
#define LTC_NO_PROTOTYPES_MEMSET
|
||||
#endif
|
||||
#define XMEMSET memset
|
||||
#endif
|
||||
#ifndef XMEMCPY
|
||||
#ifdef memcpy
|
||||
#define LTC_NO_PROTOTYPES_MEMCPY
|
||||
#endif
|
||||
#define XMEMCPY memcpy
|
||||
#endif
|
||||
#ifndef XMEMCMP
|
||||
#ifdef memcmp
|
||||
#define LTC_NO_PROTOTYPES_MEMCMP
|
||||
#endif
|
||||
#define XMEMCMP memcmp
|
||||
#endif
|
||||
#ifndef XSTRCMP
|
||||
#ifdef strcmp
|
||||
#define LTC_NO_PROTOTYPES_STRCMP
|
||||
#endif
|
||||
#define XSTRCMP strcmp
|
||||
#endif
|
||||
|
||||
#ifndef XCLOCK
|
||||
#define XCLOCK LibTomClock
|
||||
#endif
|
||||
#ifndef XCLOCKS_PER_SEC
|
||||
#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
|
||||
#endif
|
||||
|
||||
#ifndef XQSORT
|
||||
#ifdef qsort
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XQSORT LibTomQsort
|
||||
#endif
|
||||
|
||||
/* Easy button? */
|
||||
#ifdef LTC_EASY
|
||||
#define LTC_NO_CIPHERS
|
||||
#define LTC_RIJNDAEL
|
||||
#define LTC_BLOWFISH
|
||||
#define LTC_DES
|
||||
#define LTC_CAST5
|
||||
|
||||
#define LTC_NO_MODES
|
||||
#define LTC_ECB_MODE
|
||||
#define LTC_CBC_MODE
|
||||
#define LTC_CTR_MODE
|
||||
|
||||
#define LTC_NO_HASHES
|
||||
#define LTC_SHA1
|
||||
#define LTC_SHA512
|
||||
#define LTC_SHA384
|
||||
#define LTC_SHA256
|
||||
#define LTC_SHA224
|
||||
|
||||
#define LTC_NO_MACS
|
||||
#define LTC_HMAC
|
||||
#define LTC_OMAC
|
||||
#define LTC_CCM_MODE
|
||||
|
||||
#define LTC_NO_PRNGS
|
||||
#define LTC_SPRNG
|
||||
#define LTC_YARROW
|
||||
#define LTC_DEVRANDOM
|
||||
#define TRY_URANDOM_FIRST
|
||||
|
||||
#define LTC_NO_PK
|
||||
#define LTC_MRSA
|
||||
#define LTC_MECC
|
||||
#endif
|
||||
|
||||
/* Use small code where possible */
|
||||
/* #define LTC_SMALL_CODE */
|
||||
|
||||
/* Enable self-test test vector checking */
|
||||
#ifndef LTC_NO_TEST
|
||||
#define LTC_TEST
|
||||
#endif
|
||||
|
||||
/* clean the stack of functions which put private information on stack */
|
||||
/* #define LTC_CLEAN_STACK */
|
||||
|
||||
/* disable all file related functions */
|
||||
/* #define LTC_NO_FILE */
|
||||
|
||||
/* disable all forms of ASM */
|
||||
/* #define LTC_NO_ASM */
|
||||
|
||||
/* disable FAST mode */
|
||||
/* #define LTC_NO_FAST */
|
||||
|
||||
/* disable BSWAP on x86 */
|
||||
/* #define LTC_NO_BSWAP */
|
||||
|
||||
/* ---> Symmetric Block Ciphers <--- */
|
||||
#ifndef LTC_NO_CIPHERS
|
||||
|
||||
#define LTC_BLOWFISH
|
||||
#define LTC_RC2
|
||||
#define LTC_RC5
|
||||
#define LTC_RC6
|
||||
#define LTC_SAFERP
|
||||
#define LTC_RIJNDAEL
|
||||
#define LTC_XTEA
|
||||
/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
|
||||
* (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
|
||||
#define LTC_TWOFISH
|
||||
#ifndef LTC_NO_TABLES
|
||||
#define LTC_TWOFISH_TABLES
|
||||
/* #define LTC_TWOFISH_ALL_TABLES */
|
||||
#else
|
||||
#define LTC_TWOFISH_SMALL
|
||||
#endif
|
||||
/* #define LTC_TWOFISH_SMALL */
|
||||
/* LTC_DES includes EDE triple-LTC_DES */
|
||||
#define LTC_DES
|
||||
#define LTC_CAST5
|
||||
#define LTC_NOEKEON
|
||||
#define LTC_SKIPJACK
|
||||
#define LTC_SAFER
|
||||
#define LTC_KHAZAD
|
||||
#define LTC_ANUBIS
|
||||
#define LTC_ANUBIS_TWEAK
|
||||
#define LTC_KSEED
|
||||
#define LTC_KASUMI
|
||||
|
||||
#endif /* LTC_NO_CIPHERS */
|
||||
|
||||
|
||||
/* ---> Block Cipher Modes of Operation <--- */
|
||||
#ifndef LTC_NO_MODES
|
||||
|
||||
#define LTC_CFB_MODE
|
||||
#define LTC_OFB_MODE
|
||||
#define LTC_ECB_MODE
|
||||
#define LTC_CBC_MODE
|
||||
#define LTC_CTR_MODE
|
||||
|
||||
/* F8 chaining mode */
|
||||
#define LTC_F8_MODE
|
||||
|
||||
/* LRW mode */
|
||||
#define LTC_LRW_MODE
|
||||
#ifndef LTC_NO_TABLES
|
||||
/* like GCM mode this will enable 16 8x128 tables [64KB] that make
|
||||
* seeking very fast.
|
||||
*/
|
||||
#define LRW_TABLES
|
||||
#endif
|
||||
|
||||
/* XTS mode */
|
||||
#define LTC_XTS_MODE
|
||||
|
||||
#endif /* LTC_NO_MODES */
|
||||
|
||||
/* ---> One-Way Hash Functions <--- */
|
||||
#ifndef LTC_NO_HASHES
|
||||
|
||||
#define LTC_CHC_HASH
|
||||
#define LTC_WHIRLPOOL
|
||||
#define LTC_SHA512
|
||||
#define LTC_SHA384
|
||||
#define LTC_SHA256
|
||||
#define LTC_SHA224
|
||||
#define LTC_TIGER
|
||||
#define LTC_SHA1
|
||||
#define LTC_MD5
|
||||
#define LTC_MD4
|
||||
#define LTC_MD2
|
||||
#define LTC_RIPEMD128
|
||||
#define LTC_RIPEMD160
|
||||
#define LTC_RIPEMD256
|
||||
#define LTC_RIPEMD320
|
||||
|
||||
#endif /* LTC_NO_HASHES */
|
||||
|
||||
/* ---> MAC functions <--- */
|
||||
#ifndef LTC_NO_MACS
|
||||
|
||||
#define LTC_HMAC
|
||||
#define LTC_OMAC
|
||||
#define LTC_PMAC
|
||||
#define LTC_XCBC
|
||||
#define LTC_F9_MODE
|
||||
#define LTC_PELICAN
|
||||
|
||||
#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
|
||||
#error Pelican-MAC requires LTC_RIJNDAEL
|
||||
#endif
|
||||
|
||||
/* ---> Encrypt + Authenticate Modes <--- */
|
||||
|
||||
#define LTC_EAX_MODE
|
||||
#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
|
||||
#error LTC_EAX_MODE requires CTR and LTC_OMAC mode
|
||||
#endif
|
||||
|
||||
#define LTC_OCB_MODE
|
||||
#define LTC_CCM_MODE
|
||||
#define LTC_GCM_MODE
|
||||
|
||||
/* Use 64KiB tables */
|
||||
#ifndef LTC_NO_TABLES
|
||||
#define LTC_GCM_TABLES
|
||||
#endif
|
||||
|
||||
/* USE SSE2? requires GCC works on x86_32 and x86_64*/
|
||||
#ifdef LTC_GCM_TABLES
|
||||
/* #define LTC_GCM_TABLES_SSE2 */
|
||||
#endif
|
||||
|
||||
#endif /* LTC_NO_MACS */
|
||||
|
||||
/* Various tidbits of modern neatoness */
|
||||
#define LTC_BASE64
|
||||
|
||||
/* --> Pseudo Random Number Generators <--- */
|
||||
#ifndef LTC_NO_PRNGS
|
||||
|
||||
/* Yarrow */
|
||||
#define LTC_YARROW
|
||||
/* which descriptor of AES to use? */
|
||||
/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
|
||||
#define LTC_YARROW_AES 0
|
||||
|
||||
#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
|
||||
#error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
|
||||
#endif
|
||||
|
||||
/* a PRNG that simply reads from an available system source */
|
||||
#define LTC_SPRNG
|
||||
|
||||
/* The LTC_RC4 stream cipher */
|
||||
#define LTC_RC4
|
||||
|
||||
/* Fortuna PRNG */
|
||||
#define LTC_FORTUNA
|
||||
/* reseed every N calls to the read function */
|
||||
#define LTC_FORTUNA_WD 10
|
||||
/* number of pools (4..32) can save a bit of ram by lowering the count */
|
||||
#define LTC_FORTUNA_POOLS 32
|
||||
|
||||
/* Greg's LTC_SOBER128 PRNG ;-0 */
|
||||
#define LTC_SOBER128
|
||||
|
||||
/* the *nix style /dev/random device */
|
||||
#define LTC_DEVRANDOM
|
||||
/* try /dev/urandom before trying /dev/random */
|
||||
#define TRY_URANDOM_FIRST
|
||||
|
||||
#endif /* LTC_NO_PRNGS */
|
||||
|
||||
/* ---> math provider? <--- */
|
||||
#ifndef LTC_NO_MATH
|
||||
|
||||
/* LibTomMath */
|
||||
#define LTM_LTC_DESC
|
||||
|
||||
/* TomsFastMath */
|
||||
//#define TFM_LTC_DESC
|
||||
|
||||
#endif /* LTC_NO_MATH */
|
||||
|
||||
/* ---> Public Key Crypto <--- */
|
||||
#ifndef LTC_NO_PK
|
||||
|
||||
/* Include RSA support */
|
||||
#define LTC_MRSA
|
||||
|
||||
/* Include Katja (a Rabin variant like RSA) */
|
||||
/* #define MKAT */
|
||||
|
||||
/* Digital Signature Algorithm */
|
||||
#define LTC_MDSA
|
||||
|
||||
/* ECC */
|
||||
#define LTC_MECC
|
||||
|
||||
/* use Shamir's trick for point mul (speeds up signature verification) */
|
||||
#define LTC_ECC_SHAMIR
|
||||
|
||||
#if defined(TFM_LTC_DESC) && defined(LTC_MECC)
|
||||
#define LTC_MECC_ACCEL
|
||||
#endif
|
||||
|
||||
/* do we want fixed point ECC */
|
||||
/* #define LTC_MECC_FP */
|
||||
|
||||
/* Timing Resistant? */
|
||||
/* #define LTC_ECC_TIMING_RESISTANT */
|
||||
|
||||
#endif /* LTC_NO_PK */
|
||||
|
||||
/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */
|
||||
#ifndef LTC_NO_PKCS
|
||||
|
||||
#define LTC_PKCS_1
|
||||
#define LTC_PKCS_5
|
||||
|
||||
/* Include ASN.1 DER (required by DSA/RSA) */
|
||||
#define LTC_DER
|
||||
|
||||
#endif /* LTC_NO_PKCS */
|
||||
|
||||
/* cleanup */
|
||||
|
||||
#ifdef LTC_MECC
|
||||
/* Supported ECC Key Sizes */
|
||||
#ifndef LTC_NO_CURVES
|
||||
#define ECC112
|
||||
#define ECC128
|
||||
#define ECC160
|
||||
#define ECC192
|
||||
#define ECC224
|
||||
#define ECC256
|
||||
#define ECC384
|
||||
#define ECC521
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA)
|
||||
/* Include the MPI functionality? (required by the PK algorithms) */
|
||||
#define MPI
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MRSA
|
||||
#define LTC_PKCS_1
|
||||
#endif
|
||||
|
||||
#if defined(LTC_DER) && !defined(MPI)
|
||||
#error ASN.1 DER requires MPI functionality
|
||||
#endif
|
||||
|
||||
#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER)
|
||||
#error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
|
||||
#endif
|
||||
|
||||
/* THREAD management */
|
||||
#ifdef LTC_PTHREAD
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
|
||||
#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
|
||||
#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL);
|
||||
#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x);
|
||||
#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x);
|
||||
|
||||
#else
|
||||
|
||||
/* default no functions */
|
||||
#define LTC_MUTEX_GLOBAL(x)
|
||||
#define LTC_MUTEX_PROTO(x)
|
||||
#define LTC_MUTEX_TYPE(x)
|
||||
#define LTC_MUTEX_INIT(x)
|
||||
#define LTC_MUTEX_LOCK(x)
|
||||
#define LTC_MUTEX_UNLOCK(x)
|
||||
|
||||
#endif
|
||||
|
||||
/* Debuggers */
|
||||
|
||||
/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */
|
||||
/* #define LTC_VALGRIND */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */
|
||||
/* $Revision: 1.73 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
378
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_hash.h
vendored
Normal file
378
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_hash.h
vendored
Normal file
@ -0,0 +1,378 @@
|
||||
/* ---- HASH FUNCTIONS ---- */
|
||||
#ifdef LTC_SHA512
|
||||
struct sha512_state {
|
||||
ulong64 length, state[8];
|
||||
unsigned long curlen;
|
||||
unsigned char buf[128];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA256
|
||||
struct sha256_state {
|
||||
ulong64 length;
|
||||
ulong32 state[8], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
struct sha1_state {
|
||||
ulong64 length;
|
||||
ulong32 state[5], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD5
|
||||
struct md5_state {
|
||||
ulong64 length;
|
||||
ulong32 state[4], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD4
|
||||
struct md4_state {
|
||||
ulong64 length;
|
||||
ulong32 state[4], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TIGER
|
||||
struct tiger_state {
|
||||
ulong64 state[3], length;
|
||||
unsigned long curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD2
|
||||
struct md2_state {
|
||||
unsigned char chksum[16], X[48], buf[16];
|
||||
unsigned long curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD128
|
||||
struct rmd128_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD160
|
||||
struct rmd160_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[5];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD256
|
||||
struct rmd256_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD320
|
||||
struct rmd320_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[10];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
struct whirlpool_state {
|
||||
ulong64 length, state[8];
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CHC_HASH
|
||||
struct chc_state {
|
||||
ulong64 length;
|
||||
unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
|
||||
ulong32 curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Hash_state {
|
||||
#ifdef LTC_CHC_HASH
|
||||
struct chc_state chc;
|
||||
#endif
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
struct whirlpool_state whirlpool;
|
||||
#endif
|
||||
#ifdef LTC_SHA512
|
||||
struct sha512_state sha512;
|
||||
#endif
|
||||
#ifdef LTC_SHA256
|
||||
struct sha256_state sha256;
|
||||
#endif
|
||||
#ifdef LTC_SHA1
|
||||
struct sha1_state sha1;
|
||||
#endif
|
||||
#ifdef LTC_MD5
|
||||
struct md5_state md5;
|
||||
#endif
|
||||
#ifdef LTC_MD4
|
||||
struct md4_state md4;
|
||||
#endif
|
||||
#ifdef LTC_MD2
|
||||
struct md2_state md2;
|
||||
#endif
|
||||
#ifdef LTC_TIGER
|
||||
struct tiger_state tiger;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD128
|
||||
struct rmd128_state rmd128;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD160
|
||||
struct rmd160_state rmd160;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD256
|
||||
struct rmd256_state rmd256;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD320
|
||||
struct rmd320_state rmd320;
|
||||
#endif
|
||||
void *data;
|
||||
} hash_state;
|
||||
|
||||
/** hash descriptor */
|
||||
extern struct ltc_hash_descriptor {
|
||||
/** name of hash */
|
||||
char *name;
|
||||
/** internal ID */
|
||||
unsigned char ID;
|
||||
/** Size of digest in octets */
|
||||
unsigned long hashsize;
|
||||
/** Input block size in octets */
|
||||
unsigned long blocksize;
|
||||
/** ASN.1 OID */
|
||||
unsigned long OID[16];
|
||||
/** Length of DER encoding */
|
||||
unsigned long OIDlen;
|
||||
|
||||
/** Init a hash state
|
||||
@param hash The hash to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*init)(hash_state *hash);
|
||||
/** Process a block of data
|
||||
@param hash The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
|
||||
/** Produce the digest and store it
|
||||
@param hash The hash state
|
||||
@param out [out] The destination of the digest
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*done)(hash_state *hash, unsigned char *out);
|
||||
/** Self-test
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
|
||||
/* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
|
||||
int (*hmac_block)(const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
} hash_descriptor[];
|
||||
|
||||
#ifdef LTC_CHC_HASH
|
||||
int chc_register(int cipher);
|
||||
int chc_init(hash_state * md);
|
||||
int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int chc_done(hash_state * md, unsigned char *hash);
|
||||
int chc_test(void);
|
||||
extern const struct ltc_hash_descriptor chc_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
int whirlpool_init(hash_state * md);
|
||||
int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int whirlpool_done(hash_state * md, unsigned char *hash);
|
||||
int whirlpool_test(void);
|
||||
extern const struct ltc_hash_descriptor whirlpool_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA512
|
||||
int sha512_init(hash_state * md);
|
||||
int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha512_done(hash_state * md, unsigned char *hash);
|
||||
int sha512_test(void);
|
||||
extern const struct ltc_hash_descriptor sha512_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA384
|
||||
#ifndef LTC_SHA512
|
||||
#error LTC_SHA512 is required for LTC_SHA384
|
||||
#endif
|
||||
int sha384_init(hash_state * md);
|
||||
#define sha384_process sha512_process
|
||||
int sha384_done(hash_state * md, unsigned char *hash);
|
||||
int sha384_test(void);
|
||||
extern const struct ltc_hash_descriptor sha384_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA256
|
||||
int sha256_init(hash_state * md);
|
||||
int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha256_done(hash_state * md, unsigned char *hash);
|
||||
int sha256_test(void);
|
||||
extern const struct ltc_hash_descriptor sha256_desc;
|
||||
|
||||
#ifdef LTC_SHA224
|
||||
#ifndef LTC_SHA256
|
||||
#error LTC_SHA256 is required for LTC_SHA224
|
||||
#endif
|
||||
int sha224_init(hash_state * md);
|
||||
#define sha224_process sha256_process
|
||||
int sha224_done(hash_state * md, unsigned char *hash);
|
||||
int sha224_test(void);
|
||||
extern const struct ltc_hash_descriptor sha224_desc;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
int sha1_init(hash_state * md);
|
||||
int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha1_done(hash_state * md, unsigned char *hash);
|
||||
int sha1_test(void);
|
||||
extern const struct ltc_hash_descriptor sha1_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD5
|
||||
int md5_init(hash_state * md);
|
||||
int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md5_done(hash_state * md, unsigned char *hash);
|
||||
int md5_test(void);
|
||||
extern const struct ltc_hash_descriptor md5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD4
|
||||
int md4_init(hash_state * md);
|
||||
int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md4_done(hash_state * md, unsigned char *hash);
|
||||
int md4_test(void);
|
||||
extern const struct ltc_hash_descriptor md4_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD2
|
||||
int md2_init(hash_state * md);
|
||||
int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md2_done(hash_state * md, unsigned char *hash);
|
||||
int md2_test(void);
|
||||
extern const struct ltc_hash_descriptor md2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TIGER
|
||||
int tiger_init(hash_state * md);
|
||||
int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int tiger_done(hash_state * md, unsigned char *hash);
|
||||
int tiger_test(void);
|
||||
extern const struct ltc_hash_descriptor tiger_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD128
|
||||
int rmd128_init(hash_state * md);
|
||||
int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd128_done(hash_state * md, unsigned char *hash);
|
||||
int rmd128_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd128_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD160
|
||||
int rmd160_init(hash_state * md);
|
||||
int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd160_done(hash_state * md, unsigned char *hash);
|
||||
int rmd160_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd160_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD256
|
||||
int rmd256_init(hash_state * md);
|
||||
int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd256_done(hash_state * md, unsigned char *hash);
|
||||
int rmd256_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd256_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD320
|
||||
int rmd320_init(hash_state * md);
|
||||
int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd320_done(hash_state * md, unsigned char *hash);
|
||||
int rmd320_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd320_desc;
|
||||
#endif
|
||||
|
||||
|
||||
int find_hash(const char *name);
|
||||
int find_hash_id(unsigned char ID);
|
||||
int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
|
||||
int find_hash_any(const char *name, int digestlen);
|
||||
int register_hash(const struct ltc_hash_descriptor *hash);
|
||||
int unregister_hash(const struct ltc_hash_descriptor *hash);
|
||||
int hash_is_valid(int idx);
|
||||
|
||||
LTC_MUTEX_PROTO(ltc_hash_mutex)
|
||||
|
||||
int hash_memory(int hash,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
|
||||
int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* a simple macro for making hash "process" functions */
|
||||
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
|
||||
int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \
|
||||
{ \
|
||||
unsigned long n; \
|
||||
int err; \
|
||||
LTC_ARGCHK(md != NULL); \
|
||||
LTC_ARGCHK(in != NULL); \
|
||||
if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
|
||||
return CRYPT_INVALID_ARG; \
|
||||
} \
|
||||
while (inlen > 0) { \
|
||||
if (md-> state_var .curlen == 0 && inlen >= block_size) { \
|
||||
if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \
|
||||
return err; \
|
||||
} \
|
||||
md-> state_var .length += block_size * 8; \
|
||||
in += block_size; \
|
||||
inlen -= block_size; \
|
||||
} else { \
|
||||
n = MIN(inlen, (block_size - md-> state_var .curlen)); \
|
||||
memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \
|
||||
md-> state_var .curlen += n; \
|
||||
in += n; \
|
||||
inlen -= n; \
|
||||
if (md-> state_var .curlen == block_size) { \
|
||||
if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \
|
||||
return err; \
|
||||
} \
|
||||
md-> state_var .length += 8*block_size; \
|
||||
md-> state_var .curlen = 0; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
return CRYPT_OK; \
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_hash.h,v $ */
|
||||
/* $Revision: 1.22 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
384
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_mac.h
vendored
Normal file
384
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_mac.h
vendored
Normal file
@ -0,0 +1,384 @@
|
||||
#ifdef LTC_HMAC
|
||||
typedef struct Hmac_state {
|
||||
hash_state md;
|
||||
int hash;
|
||||
hash_state hashstate;
|
||||
unsigned char *key;
|
||||
} hmac_state;
|
||||
|
||||
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
|
||||
int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen);
|
||||
int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen);
|
||||
int hmac_test(void);
|
||||
int hmac_memory(int hash,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int hmac_memory_multi(int hash,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int hmac_file(int hash, const char *fname, const unsigned char *key,
|
||||
unsigned long keylen,
|
||||
unsigned char *dst, unsigned long *dstlen);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OMAC
|
||||
|
||||
typedef struct {
|
||||
int cipher_idx,
|
||||
buflen,
|
||||
blklen;
|
||||
unsigned char block[MAXBLOCKSIZE],
|
||||
prev[MAXBLOCKSIZE],
|
||||
Lu[2][MAXBLOCKSIZE];
|
||||
symmetric_key key;
|
||||
} omac_state;
|
||||
|
||||
int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
|
||||
int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
|
||||
int omac_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int omac_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int omac_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int omac_test(void);
|
||||
#endif /* LTC_OMAC */
|
||||
|
||||
#ifdef LTC_PMAC
|
||||
|
||||
typedef struct {
|
||||
unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
|
||||
Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
|
||||
Lr[MAXBLOCKSIZE], /* L * x^-1 */
|
||||
block[MAXBLOCKSIZE], /* currently accumulated block */
|
||||
checksum[MAXBLOCKSIZE]; /* current checksum */
|
||||
|
||||
symmetric_key key; /* scheduled key for cipher */
|
||||
unsigned long block_index; /* index # for current block */
|
||||
int cipher_idx, /* cipher idx */
|
||||
block_len, /* length of block */
|
||||
buflen; /* number of bytes in the buffer */
|
||||
} pmac_state;
|
||||
|
||||
int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen);
|
||||
int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *msg, unsigned long msglen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
|
||||
int pmac_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_test(void);
|
||||
|
||||
/* internal functions */
|
||||
int pmac_ntz(unsigned long x);
|
||||
void pmac_shift_xor(pmac_state *pmac);
|
||||
|
||||
#endif /* PMAC */
|
||||
|
||||
#ifdef LTC_EAX_MODE
|
||||
|
||||
#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))
|
||||
#error LTC_EAX_MODE requires LTC_OMAC and CTR
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char N[MAXBLOCKSIZE];
|
||||
symmetric_CTR ctr;
|
||||
omac_state headeromac, ctomac;
|
||||
} eax_state;
|
||||
|
||||
int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen);
|
||||
|
||||
int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
|
||||
int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
|
||||
int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
|
||||
int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int eax_encrypt_authenticate_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int eax_decrypt_verify_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
unsigned char *tag, unsigned long taglen,
|
||||
int *stat);
|
||||
|
||||
int eax_test(void);
|
||||
#endif /* EAX MODE */
|
||||
|
||||
#ifdef LTC_OCB_MODE
|
||||
typedef struct {
|
||||
unsigned char L[MAXBLOCKSIZE], /* L value */
|
||||
Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
|
||||
Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
|
||||
Lr[MAXBLOCKSIZE], /* L * x^-1 */
|
||||
R[MAXBLOCKSIZE], /* R value */
|
||||
checksum[MAXBLOCKSIZE]; /* current checksum */
|
||||
|
||||
symmetric_key key; /* scheduled key for cipher */
|
||||
unsigned long block_index; /* index # for current block */
|
||||
int cipher, /* cipher idx */
|
||||
block_len; /* length of block */
|
||||
} ocb_state;
|
||||
|
||||
int ocb_init(ocb_state *ocb, int cipher,
|
||||
const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
|
||||
|
||||
int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
|
||||
int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
|
||||
|
||||
int ocb_done_encrypt(ocb_state *ocb,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int ocb_done_decrypt(ocb_state *ocb,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tag, unsigned long taglen, int *stat);
|
||||
|
||||
int ocb_encrypt_authenticate_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int ocb_decrypt_verify_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tag, unsigned long taglen,
|
||||
int *stat);
|
||||
|
||||
int ocb_test(void);
|
||||
|
||||
/* internal functions */
|
||||
void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
|
||||
int ocb_ntz(unsigned long x);
|
||||
int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
|
||||
|
||||
#endif /* LTC_OCB_MODE */
|
||||
|
||||
#ifdef LTC_CCM_MODE
|
||||
|
||||
#define CCM_ENCRYPT 0
|
||||
#define CCM_DECRYPT 1
|
||||
|
||||
int ccm_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
symmetric_key *uskey,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
int ccm_test(void);
|
||||
|
||||
#endif /* LTC_CCM_MODE */
|
||||
|
||||
#if defined(LRW_MODE) || defined(LTC_GCM_MODE)
|
||||
void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);
|
||||
#endif
|
||||
|
||||
|
||||
/* table shared between GCM and LRW */
|
||||
#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))
|
||||
extern const unsigned char gcm_shift_table[];
|
||||
#endif
|
||||
|
||||
#ifdef LTC_GCM_MODE
|
||||
|
||||
#define GCM_ENCRYPT 0
|
||||
#define GCM_DECRYPT 1
|
||||
|
||||
#define LTC_GCM_MODE_IV 0
|
||||
#define LTC_GCM_MODE_AAD 1
|
||||
#define LTC_GCM_MODE_TEXT 2
|
||||
|
||||
typedef struct {
|
||||
symmetric_key K;
|
||||
unsigned char H[16], /* multiplier */
|
||||
X[16], /* accumulator */
|
||||
Y[16], /* counter */
|
||||
Y_0[16], /* initial counter */
|
||||
buf[16]; /* buffer for stuff */
|
||||
|
||||
int cipher, /* which cipher */
|
||||
ivmode, /* Which mode is the IV in? */
|
||||
mode, /* mode the GCM code is in */
|
||||
buflen; /* length of data in buf */
|
||||
|
||||
ulong64 totlen, /* 64-bit counter used for IV and AAD */
|
||||
pttotlen; /* 64-bit counter for the PT */
|
||||
|
||||
#ifdef LTC_GCM_TABLES
|
||||
unsigned char PC[16][256][16] /* 16 tables of 8x128 */
|
||||
#ifdef LTC_GCM_TABLES_SSE2
|
||||
__attribute__ ((aligned (16)))
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
} gcm_state;
|
||||
|
||||
void gcm_mult_h(gcm_state *gcm, unsigned char *I);
|
||||
|
||||
int gcm_init(gcm_state *gcm, int cipher,
|
||||
const unsigned char *key, int keylen);
|
||||
|
||||
int gcm_reset(gcm_state *gcm);
|
||||
|
||||
int gcm_add_iv(gcm_state *gcm,
|
||||
const unsigned char *IV, unsigned long IVlen);
|
||||
|
||||
int gcm_add_aad(gcm_state *gcm,
|
||||
const unsigned char *adata, unsigned long adatalen);
|
||||
|
||||
int gcm_process(gcm_state *gcm,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
int direction);
|
||||
|
||||
int gcm_done(gcm_state *gcm,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int gcm_memory( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
int gcm_test(void);
|
||||
|
||||
#endif /* LTC_GCM_MODE */
|
||||
|
||||
#ifdef LTC_PELICAN
|
||||
|
||||
typedef struct pelican_state
|
||||
{
|
||||
symmetric_key K;
|
||||
unsigned char state[16];
|
||||
int buflen;
|
||||
} pelican_state;
|
||||
|
||||
int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen);
|
||||
int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen);
|
||||
int pelican_done(pelican_state *pelmac, unsigned char *out);
|
||||
int pelican_test(void);
|
||||
|
||||
int pelican_memory(const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XCBC
|
||||
|
||||
/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */
|
||||
#define LTC_XCBC_PURE 0x8000UL
|
||||
|
||||
typedef struct {
|
||||
unsigned char K[3][MAXBLOCKSIZE],
|
||||
IV[MAXBLOCKSIZE];
|
||||
|
||||
symmetric_key key;
|
||||
|
||||
int cipher,
|
||||
buflen,
|
||||
blocksize;
|
||||
} xcbc_state;
|
||||
|
||||
int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen);
|
||||
int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int xcbc_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F9_MODE
|
||||
|
||||
typedef struct {
|
||||
unsigned char akey[MAXBLOCKSIZE],
|
||||
ACC[MAXBLOCKSIZE],
|
||||
IV[MAXBLOCKSIZE];
|
||||
|
||||
symmetric_key key;
|
||||
|
||||
int cipher,
|
||||
buflen,
|
||||
keylen,
|
||||
blocksize;
|
||||
} f9_state;
|
||||
|
||||
int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen);
|
||||
int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen);
|
||||
int f9_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int f9_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int f9_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int f9_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_mac.h,v $ */
|
||||
/* $Revision: 1.23 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
424
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_macros.h
vendored
Normal file
424
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_macros.h
vendored
Normal file
@ -0,0 +1,424 @@
|
||||
/* fix for MSVC ...evil! */
|
||||
#ifdef _MSC_VER
|
||||
#define CONST64(n) n ## ui64
|
||||
typedef unsigned __int64 ulong64;
|
||||
#else
|
||||
#define CONST64(n) n ## ULL
|
||||
typedef unsigned long long ulong64;
|
||||
#endif
|
||||
|
||||
/* this is the "32-bit at least" data type
|
||||
* Re-define it to suit your platform but it must be at least 32-bits
|
||||
*/
|
||||
#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__))
|
||||
typedef unsigned ulong32;
|
||||
#else
|
||||
typedef unsigned long ulong32;
|
||||
#endif
|
||||
|
||||
/* ---- HELPER MACROS ---- */
|
||||
#ifdef ENDIAN_NEUTRAL
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
|
||||
((unsigned long)((y)[2] & 255)<<16) | \
|
||||
((unsigned long)((y)[1] & 255)<<8) | \
|
||||
((unsigned long)((y)[0] & 255)); }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
|
||||
((unsigned long)((y)[1] & 255)<<16) | \
|
||||
((unsigned long)((y)[2] & 255)<<8) | \
|
||||
((unsigned long)((y)[3] & 255)); }
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
|
||||
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#endif /* ENDIAN_NEUTRAL */
|
||||
|
||||
#ifdef ENDIAN_LITTLE
|
||||
|
||||
#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"bswapl %0 \n\t" \
|
||||
"movl %0,(%1)\n\t" \
|
||||
"bswapl %0 \n\t" \
|
||||
::"r"(x), "r"(y));
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"movl (%1),%0\n\t" \
|
||||
"bswapl %0\n\t" \
|
||||
:"=r"(x): "r"(y));
|
||||
|
||||
#else
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
|
||||
((unsigned long)((y)[1] & 255)<<16) | \
|
||||
((unsigned long)((y)[2] & 255)<<8) | \
|
||||
((unsigned long)((y)[3] & 255)); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* x86_64 processor */
|
||||
#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"bswapq %0 \n\t" \
|
||||
"movq %0,(%1)\n\t" \
|
||||
"bswapq %0 \n\t" \
|
||||
::"r"(x), "r"(y));
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"movq (%1),%0\n\t" \
|
||||
"bswapq %0\n\t" \
|
||||
:"=r"(x): "r"(y));
|
||||
|
||||
#else
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
|
||||
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENDIAN_32BITWORD
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
XMEMCPY(&(x), y, 4);
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#else /* 64-bit words then */
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ XMEMCPY(&(x), y, 8); }
|
||||
|
||||
#endif /* ENDIAN_64BITWORD */
|
||||
|
||||
#endif /* ENDIAN_LITTLE */
|
||||
|
||||
#ifdef ENDIAN_BIG
|
||||
#define STORE32L(x, y) \
|
||||
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
|
||||
((unsigned long)((y)[2] & 255)<<16) | \
|
||||
((unsigned long)((y)[1] & 255)<<8) | \
|
||||
((unsigned long)((y)[0] & 255)); }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#ifdef ENDIAN_32BITWORD
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
XMEMCPY(&(x), y, 4);
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
|
||||
(((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#else /* 64-bit words then */
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ XMEMCPY(&(x), y, 8); }
|
||||
|
||||
#endif /* ENDIAN_64BITWORD */
|
||||
#endif /* ENDIAN_BIG */
|
||||
|
||||
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
|
||||
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
|
||||
|
||||
|
||||
/* 32-bit Rotates */
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
/* instrinsic rotate */
|
||||
#include <stdlib.h>
|
||||
#pragma intrinsic(_lrotr,_lrotl)
|
||||
#define ROR(x,n) _lrotr(x,n)
|
||||
#define ROL(x,n) _lrotl(x,n)
|
||||
#define RORc(x,n) _lrotr(x,n)
|
||||
#define ROLc(x,n) _lrotl(x,n)
|
||||
|
||||
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
|
||||
|
||||
static inline unsigned ROL(unsigned word, int i)
|
||||
{
|
||||
asm ("roll %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned ROR(unsigned word, int i)
|
||||
{
|
||||
asm ("rorl %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned ROLc(unsigned word, const int i)
|
||||
{
|
||||
asm ("roll %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned RORc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rorl %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ROLc ROL
|
||||
#define RORc ROR
|
||||
|
||||
#endif
|
||||
|
||||
#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
|
||||
|
||||
static inline unsigned ROL(unsigned word, int i)
|
||||
{
|
||||
asm ("rotlw %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"r" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned ROR(unsigned word, int i)
|
||||
{
|
||||
asm ("rotlw %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"r" (32-i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned ROLc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rotlwi %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned RORc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rotrwi %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ROLc ROL
|
||||
#define RORc ROR
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* rotates the hard way */
|
||||
#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* 64-bit Rotates */
|
||||
#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM)
|
||||
|
||||
static inline unsigned long ROL64(unsigned long word, int i)
|
||||
{
|
||||
asm("rolq %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned long ROR64(unsigned long word, int i)
|
||||
{
|
||||
asm("rorq %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned long ROL64c(unsigned long word, const int i)
|
||||
{
|
||||
asm("rolq %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"J" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned long ROR64c(unsigned long word, const int i)
|
||||
{
|
||||
asm("rorq %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"J" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else /* LTC_NO_ROLC */
|
||||
|
||||
#define ROL64c ROL64
|
||||
#define ROR64c ROR64
|
||||
|
||||
#endif
|
||||
|
||||
#else /* Not x86_64 */
|
||||
|
||||
#define ROL64(x, y) \
|
||||
( (((x)<<((ulong64)(y)&63)) | \
|
||||
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROR64(x, y) \
|
||||
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
|
||||
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROL64c(x, y) \
|
||||
( (((x)<<((ulong64)(y)&63)) | \
|
||||
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROR64c(x, y) \
|
||||
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
|
||||
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
|
||||
#endif
|
||||
|
||||
/* extract a byte portably */
|
||||
#ifdef _MSC_VER
|
||||
#define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
|
||||
#else
|
||||
#define byte(x, n) (((x) >> (8 * (n))) & 255)
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */
|
||||
/* $Revision: 1.15 $ */
|
||||
/* $Date: 2006/11/29 23:43:57 $ */
|
||||
500
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_math.h
vendored
Normal file
500
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_math.h
vendored
Normal file
@ -0,0 +1,500 @@
|
||||
/** math functions **/
|
||||
|
||||
#define LTC_MP_LT -1
|
||||
#define LTC_MP_EQ 0
|
||||
#define LTC_MP_GT 1
|
||||
|
||||
#define LTC_MP_NO 0
|
||||
#define LTC_MP_YES 1
|
||||
|
||||
#ifndef LTC_MECC
|
||||
typedef void ecc_point;
|
||||
#endif
|
||||
|
||||
#ifndef LTC_MRSA
|
||||
typedef void rsa_key;
|
||||
#endif
|
||||
|
||||
/** math descriptor */
|
||||
typedef struct {
|
||||
/** Name of the math provider */
|
||||
char *name;
|
||||
|
||||
/** Bits per digit, amount of bits must fit in an unsigned long */
|
||||
int bits_per_digit;
|
||||
|
||||
/* ---- init/deinit functions ---- */
|
||||
|
||||
/** initialize a bignum
|
||||
@param a The number to initialize
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*init)(void **a);
|
||||
|
||||
/** init copy
|
||||
@param dst The number to initialize and write to
|
||||
@param src The number to copy from
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*init_copy)(void **dst, void *src);
|
||||
|
||||
/** deinit
|
||||
@param a The number to free
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
void (*deinit)(void *a);
|
||||
|
||||
/* ---- data movement ---- */
|
||||
|
||||
/** negate
|
||||
@param src The number to negate
|
||||
@param dst The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*neg)(void *src, void *dst);
|
||||
|
||||
/** copy
|
||||
@param src The number to copy from
|
||||
@param dst The number to write to
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*copy)(void *src, void *dst);
|
||||
|
||||
/* ---- trivial low level functions ---- */
|
||||
|
||||
/** set small constant
|
||||
@param a Number to write to
|
||||
@param n Source upto bits_per_digit (actually meant for very small constants)
|
||||
@return CRYPT_OK on succcess
|
||||
*/
|
||||
int (*set_int)(void *a, unsigned long n);
|
||||
|
||||
/** get small constant
|
||||
@param a Number to read, only fetches upto bits_per_digit from the number
|
||||
@return The lower bits_per_digit of the integer (unsigned)
|
||||
*/
|
||||
unsigned long (*get_int)(void *a);
|
||||
|
||||
/** get digit n
|
||||
@param a The number to read from
|
||||
@param n The number of the digit to fetch
|
||||
@return The bits_per_digit sized n'th digit of a
|
||||
*/
|
||||
unsigned long (*get_digit)(void *a, int n);
|
||||
|
||||
/** Get the number of digits that represent the number
|
||||
@param a The number to count
|
||||
@return The number of digits used to represent the number
|
||||
*/
|
||||
int (*get_digit_count)(void *a);
|
||||
|
||||
/** compare two integers
|
||||
@param a The left side integer
|
||||
@param b The right side integer
|
||||
@return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
|
||||
*/
|
||||
int (*compare)(void *a, void *b);
|
||||
|
||||
/** compare against int
|
||||
@param a The left side integer
|
||||
@param b The right side integer (upto bits_per_digit)
|
||||
@return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
|
||||
*/
|
||||
int (*compare_d)(void *a, unsigned long n);
|
||||
|
||||
/** Count the number of bits used to represent the integer
|
||||
@param a The integer to count
|
||||
@return The number of bits required to represent the integer
|
||||
*/
|
||||
int (*count_bits)(void * a);
|
||||
|
||||
/** Count the number of LSB bits which are zero
|
||||
@param a The integer to count
|
||||
@return The number of contiguous zero LSB bits
|
||||
*/
|
||||
int (*count_lsb_bits)(void *a);
|
||||
|
||||
/** Compute a power of two
|
||||
@param a The integer to store the power in
|
||||
@param n The power of two you want to store (a = 2^n)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*twoexpt)(void *a , int n);
|
||||
|
||||
/* ---- radix conversions ---- */
|
||||
|
||||
/** read ascii string
|
||||
@param a The integer to store into
|
||||
@param str The string to read
|
||||
@param radix The radix the integer has been represented in (2-64)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*read_radix)(void *a, const char *str, int radix);
|
||||
|
||||
/** write number to string
|
||||
@param a The integer to store
|
||||
@param str The destination for the string
|
||||
@param radix The radix the integer is to be represented in (2-64)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*write_radix)(void *a, char *str, int radix);
|
||||
|
||||
/** get size as unsigned char string
|
||||
@param a The integer to get the size (when stored in array of octets)
|
||||
@return The length of the integer
|
||||
*/
|
||||
unsigned long (*unsigned_size)(void *a);
|
||||
|
||||
/** store an integer as an array of octets
|
||||
@param src The integer to store
|
||||
@param dst The buffer to store the integer in
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*unsigned_write)(void *src, unsigned char *dst);
|
||||
|
||||
/** read an array of octets and store as integer
|
||||
@param dst The integer to load
|
||||
@param src The array of octets
|
||||
@param len The number of octets
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len);
|
||||
|
||||
/* ---- basic math ---- */
|
||||
|
||||
/** add two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer
|
||||
@param c The destination of "a + b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*add)(void *a, void *b, void *c);
|
||||
|
||||
|
||||
/** add two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a + b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*addi)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** subtract two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer
|
||||
@param c The destination of "a - b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sub)(void *a, void *b, void *c);
|
||||
|
||||
/** subtract two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a - b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*subi)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** multiply two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a * b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mul)(void *a, void *b, void *c);
|
||||
|
||||
/** multiply two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a * b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*muli)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** Square an integer
|
||||
@param a The integer to square
|
||||
@param b The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sqr)(void *a, void *b);
|
||||
|
||||
/** Divide an integer
|
||||
@param a The dividend
|
||||
@param b The divisor
|
||||
@param c The quotient (can be NULL to signify don't care)
|
||||
@param d The remainder (can be NULL to signify don't care)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mpdiv)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** divide by two
|
||||
@param a The integer to divide (shift right)
|
||||
@param b The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*div_2)(void *a, void *b);
|
||||
|
||||
/** Get remainder (small value)
|
||||
@param a The integer to reduce
|
||||
@param b The modulus (upto bits_per_digit in length)
|
||||
@param c The destination for the residue
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*modi)(void *a, unsigned long b, unsigned long *c);
|
||||
|
||||
/** gcd
|
||||
@param a The first integer
|
||||
@param b The second integer
|
||||
@param c The destination for (a, b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*gcd)(void *a, void *b, void *c);
|
||||
|
||||
/** lcm
|
||||
@param a The first integer
|
||||
@param b The second integer
|
||||
@param c The destination for [a, b]
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*lcm)(void *a, void *b, void *c);
|
||||
|
||||
/** Modular multiplication
|
||||
@param a The first source
|
||||
@param b The second source
|
||||
@param c The modulus
|
||||
@param d The destination (a*b mod c)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mulmod)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** Modular squaring
|
||||
@param a The first source
|
||||
@param b The modulus
|
||||
@param c The destination (a*a mod b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sqrmod)(void *a, void *b, void *c);
|
||||
|
||||
/** Modular inversion
|
||||
@param a The value to invert
|
||||
@param b The modulus
|
||||
@param c The destination (1/a mod b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*invmod)(void *, void *, void *);
|
||||
|
||||
/* ---- reduction ---- */
|
||||
|
||||
/** setup montgomery
|
||||
@param a The modulus
|
||||
@param b The destination for the reduction digit
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_setup)(void *a, void **b);
|
||||
|
||||
/** get normalization value
|
||||
@param a The destination for the normalization value
|
||||
@param b The modulus
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_normalization)(void *a, void *b);
|
||||
|
||||
/** reduce a number
|
||||
@param a The number [and dest] to reduce
|
||||
@param b The modulus
|
||||
@param c The value "b" from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_reduce)(void *a, void *b, void *c);
|
||||
|
||||
/** clean up (frees memory)
|
||||
@param a The value "b" from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
void (*montgomery_deinit)(void *a);
|
||||
|
||||
/* ---- exponentiation ---- */
|
||||
|
||||
/** Modular exponentiation
|
||||
@param a The base integer
|
||||
@param b The power (can be negative) integer
|
||||
@param c The modulus integer
|
||||
@param d The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*exptmod)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** Primality testing
|
||||
@param a The integer to test
|
||||
@param b The destination of the result (FP_YES if prime)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*isprime)(void *a, int *b);
|
||||
|
||||
/* ---- (optional) ecc point math ---- */
|
||||
|
||||
/** ECC GF(p) point multiplication (from the NIST curves)
|
||||
@param k The integer to multiply the point by
|
||||
@param G The point to multiply
|
||||
@param R The destination for kG
|
||||
@param modulus The modulus for the field
|
||||
@param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
/** ECC GF(p) point addition
|
||||
@param P The first point
|
||||
@param Q The second point
|
||||
@param R The destination of P + Q
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/** ECC GF(p) point double
|
||||
@param P The first point
|
||||
@param R The destination of 2P
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)
|
||||
@param P The point to map
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
@remark The mapping can be different but keep in mind a ecc_point only has three
|
||||
integers (x,y,z) so if you use a different mapping you have to make it fit.
|
||||
*/
|
||||
int (*ecc_map)(ecc_point *P, void *modulus, void *mp);
|
||||
|
||||
/** Computes kA*A + kB*B = C using Shamir's Trick
|
||||
@param A First point to multiply
|
||||
@param kA What to multiple A by
|
||||
@param B Second point to multiply
|
||||
@param kB What to multiple B by
|
||||
@param C [out] Destination point (can overlap with A or B
|
||||
@param modulus Modulus for curve
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_mul2add)(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C,
|
||||
void *modulus);
|
||||
|
||||
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
|
||||
|
||||
/** RSA Key Generation
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index of the PRNG desired
|
||||
@param size The size of the modulus (key size) desired (octets)
|
||||
@param e The "e" value (public key). e==65537 is a good choice
|
||||
@param key [out] Destination of a newly created private key pair
|
||||
@return CRYPT_OK if successful, upon error all allocated ram is freed
|
||||
*/
|
||||
int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key);
|
||||
|
||||
|
||||
/** RSA exponentiation
|
||||
@param in The octet array representing the base
|
||||
@param inlen The length of the input
|
||||
@param out The destination (to be stored in an octet array format)
|
||||
@param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus)
|
||||
@param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
|
||||
@param key The RSA key to use
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*rsa_me)(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
rsa_key *key);
|
||||
} ltc_math_descriptor;
|
||||
|
||||
extern ltc_math_descriptor ltc_mp;
|
||||
|
||||
int ltc_init_multi(void **a, ...);
|
||||
void ltc_deinit_multi(void *a, ...);
|
||||
|
||||
#ifdef LTM_DESC
|
||||
extern const ltc_math_descriptor ltm_desc;
|
||||
#endif
|
||||
|
||||
#ifdef TFM_DESC
|
||||
extern const ltc_math_descriptor tfm_desc;
|
||||
#endif
|
||||
|
||||
#ifdef GMP_DESC
|
||||
extern const ltc_math_descriptor gmp_desc;
|
||||
#endif
|
||||
|
||||
#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE)
|
||||
|
||||
#define MP_DIGIT_BIT ltc_mp.bits_per_digit
|
||||
|
||||
/* some handy macros */
|
||||
#define mp_init(a) ltc_mp.init(a)
|
||||
#define mp_init_multi ltc_init_multi
|
||||
#define mp_clear(a) ltc_mp.deinit(a)
|
||||
#define mp_clear_multi ltc_deinit_multi
|
||||
#define mp_init_copy(a, b) ltc_mp.init_copy(a, b)
|
||||
|
||||
#define mp_neg(a, b) ltc_mp.neg(a, b)
|
||||
#define mp_copy(a, b) ltc_mp.copy(a, b)
|
||||
|
||||
#define mp_set(a, b) ltc_mp.set_int(a, b)
|
||||
#define mp_set_int(a, b) ltc_mp.set_int(a, b)
|
||||
#define mp_get_int(a) ltc_mp.get_int(a)
|
||||
#define mp_get_digit(a, n) ltc_mp.get_digit(a, n)
|
||||
#define mp_get_digit_count(a) ltc_mp.get_digit_count(a)
|
||||
#define mp_cmp(a, b) ltc_mp.compare(a, b)
|
||||
#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b)
|
||||
#define mp_count_bits(a) ltc_mp.count_bits(a)
|
||||
#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a)
|
||||
#define mp_2expt(a, b) ltc_mp.twoexpt(a, b)
|
||||
|
||||
#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c)
|
||||
#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c)
|
||||
#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
|
||||
#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
|
||||
#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
|
||||
|
||||
#define mp_add(a, b, c) ltc_mp.add(a, b, c)
|
||||
#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c)
|
||||
#define mp_sub(a, b, c) ltc_mp.sub(a, b, c)
|
||||
#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c)
|
||||
#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
|
||||
#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
|
||||
#define mp_sqr(a, b) ltc_mp.sqr(a, b)
|
||||
#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
|
||||
#define mp_div_2(a, b) ltc_mp.div_2(a, b)
|
||||
#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
|
||||
#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c)
|
||||
#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c)
|
||||
#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c)
|
||||
|
||||
#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d)
|
||||
#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c)
|
||||
#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c)
|
||||
|
||||
#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b)
|
||||
#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b)
|
||||
#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c)
|
||||
#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a)
|
||||
|
||||
#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
|
||||
#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c)
|
||||
|
||||
#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)
|
||||
#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)
|
||||
#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0);
|
||||
|
||||
#define mp_tohex(a, b) mp_toradix(a, b, 16)
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_math.h,v $ */
|
||||
/* $Revision: 1.44 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
23
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_misc.h
vendored
Normal file
23
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_misc.h
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/* ---- LTC_BASE64 Routines ---- */
|
||||
#ifdef LTC_BASE64
|
||||
int base64_encode(const unsigned char *in, unsigned long len,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int base64_decode(const unsigned char *in, unsigned long len,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
#endif
|
||||
|
||||
/* ---- MEM routines ---- */
|
||||
void zeromem(void *dst, size_t len);
|
||||
void burn_stack(unsigned long len);
|
||||
|
||||
const char *error_to_string(int err);
|
||||
|
||||
extern const char *crypt_build_settings;
|
||||
|
||||
/* ---- HMM ---- */
|
||||
int crypt_fsa(void *mp, ...);
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
558
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_pk.h
vendored
Normal file
558
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_pk.h
vendored
Normal file
@ -0,0 +1,558 @@
|
||||
/* ---- NUMBER THEORY ---- */
|
||||
|
||||
enum {
|
||||
PK_PUBLIC=0,
|
||||
PK_PRIVATE=1
|
||||
};
|
||||
|
||||
int rand_prime(void *N, long len, prng_state *prng, int wprng);
|
||||
|
||||
/* ---- RSA ---- */
|
||||
#ifdef LTC_MRSA
|
||||
|
||||
/* Min and Max RSA key sizes (in bits) */
|
||||
#define MIN_RSA_SIZE 1024
|
||||
#define MAX_RSA_SIZE 4096
|
||||
|
||||
/** RSA LTC_PKCS style key */
|
||||
typedef struct Rsa_key {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
/** The public exponent */
|
||||
void *e;
|
||||
/** The private exponent */
|
||||
void *d;
|
||||
/** The modulus */
|
||||
void *N;
|
||||
/** The p factor of N */
|
||||
void *p;
|
||||
/** The q factor of N */
|
||||
void *q;
|
||||
/** The 1/q mod p CRT param */
|
||||
void *qP;
|
||||
/** The d mod (p - 1) CRT param */
|
||||
void *dP;
|
||||
/** The d mod (q - 1) CRT param */
|
||||
void *dQ;
|
||||
} rsa_key;
|
||||
|
||||
int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
|
||||
|
||||
int rsa_exptmod(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
rsa_key *key);
|
||||
|
||||
void rsa_free(rsa_key *key);
|
||||
|
||||
/* These use LTC_PKCS #1 v2.0 padding */
|
||||
#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \
|
||||
rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key)
|
||||
|
||||
#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \
|
||||
rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key)
|
||||
|
||||
#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \
|
||||
rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key)
|
||||
|
||||
#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \
|
||||
rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key)
|
||||
|
||||
/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */
|
||||
int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key);
|
||||
|
||||
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
int hash_idx, int padding,
|
||||
int *stat, rsa_key *key);
|
||||
|
||||
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
int padding,
|
||||
prng_state *prng, int prng_idx,
|
||||
int hash_idx, unsigned long saltlen,
|
||||
rsa_key *key);
|
||||
|
||||
int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int padding,
|
||||
int hash_idx, unsigned long saltlen,
|
||||
int *stat, rsa_key *key);
|
||||
|
||||
/* LTC_PKCS #1 import/export */
|
||||
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
|
||||
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
|
||||
|
||||
/* Ladik: Added for verifying Blizzard strong signature verification */
|
||||
int rsa_verify_simple(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat,
|
||||
rsa_key *key);
|
||||
|
||||
#endif
|
||||
|
||||
/* ---- Katja ---- */
|
||||
#ifdef MKAT
|
||||
|
||||
/* Min and Max KAT key sizes (in bits) */
|
||||
#define MIN_KAT_SIZE 1024
|
||||
#define MAX_KAT_SIZE 4096
|
||||
|
||||
/** Katja LTC_PKCS style key */
|
||||
typedef struct KAT_key {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
/** The private exponent */
|
||||
void *d;
|
||||
/** The modulus */
|
||||
void *N;
|
||||
/** The p factor of N */
|
||||
void *p;
|
||||
/** The q factor of N */
|
||||
void *q;
|
||||
/** The 1/q mod p CRT param */
|
||||
void *qP;
|
||||
/** The d mod (p - 1) CRT param */
|
||||
void *dP;
|
||||
/** The d mod (q - 1) CRT param */
|
||||
void *dQ;
|
||||
/** The pq param */
|
||||
void *pq;
|
||||
} katja_key;
|
||||
|
||||
int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key);
|
||||
|
||||
int katja_exptmod(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
katja_key *key);
|
||||
|
||||
void katja_free(katja_key *key);
|
||||
|
||||
/* These use LTC_PKCS #1 v2.0 padding */
|
||||
int katja_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
prng_state *prng, int prng_idx, int hash_idx, katja_key *key);
|
||||
|
||||
int katja_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
int hash_idx, int *stat,
|
||||
katja_key *key);
|
||||
|
||||
/* LTC_PKCS #1 import/export */
|
||||
int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key);
|
||||
int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);
|
||||
|
||||
#endif
|
||||
|
||||
/* ---- ECC Routines ---- */
|
||||
#ifdef LTC_MECC
|
||||
|
||||
/* size of our temp buffers for exported keys */
|
||||
#define ECC_BUF_SIZE 256
|
||||
|
||||
/* max private key size */
|
||||
#define ECC_MAXSIZE 66
|
||||
|
||||
/** Structure defines a NIST GF(p) curve */
|
||||
typedef struct {
|
||||
/** The size of the curve in octets */
|
||||
int size;
|
||||
|
||||
/** name of curve */
|
||||
char *name;
|
||||
|
||||
/** The prime that defines the field the curve is in (encoded in hex) */
|
||||
char *prime;
|
||||
|
||||
/** The fields B param (hex) */
|
||||
char *B;
|
||||
|
||||
/** The order of the curve (hex) */
|
||||
char *order;
|
||||
|
||||
/** The x co-ordinate of the base point on the curve (hex) */
|
||||
char *Gx;
|
||||
|
||||
/** The y co-ordinate of the base point on the curve (hex) */
|
||||
char *Gy;
|
||||
} ltc_ecc_set_type;
|
||||
|
||||
/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
|
||||
typedef struct {
|
||||
/** The x co-ordinate */
|
||||
void *x;
|
||||
|
||||
/** The y co-ordinate */
|
||||
void *y;
|
||||
|
||||
/** The z co-ordinate */
|
||||
void *z;
|
||||
} ecc_point;
|
||||
|
||||
/** An ECC key */
|
||||
typedef struct {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
|
||||
/** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */
|
||||
int idx;
|
||||
|
||||
/** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */
|
||||
const ltc_ecc_set_type *dp;
|
||||
|
||||
/** The public key */
|
||||
ecc_point pubkey;
|
||||
|
||||
/** The private key */
|
||||
void *k;
|
||||
} ecc_key;
|
||||
|
||||
/** the ECC params provided */
|
||||
extern const ltc_ecc_set_type ltc_ecc_sets[];
|
||||
|
||||
int ecc_test(void);
|
||||
void ecc_sizes(int *low, int *high);
|
||||
int ecc_get_size(ecc_key *key);
|
||||
|
||||
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
|
||||
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
|
||||
void ecc_free(ecc_key *key);
|
||||
|
||||
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
|
||||
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
|
||||
|
||||
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
|
||||
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
|
||||
|
||||
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
ecc_key *key);
|
||||
|
||||
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
ecc_key *key);
|
||||
|
||||
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, ecc_key *key);
|
||||
|
||||
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, ecc_key *key);
|
||||
|
||||
/* low level functions */
|
||||
ecc_point *ltc_ecc_new_point(void);
|
||||
void ltc_ecc_del_point(ecc_point *p);
|
||||
int ltc_ecc_is_valid_idx(int n);
|
||||
|
||||
/* point ops (mp == montgomery digit) */
|
||||
#if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC)
|
||||
/* R = 2P */
|
||||
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/* R = P + Q */
|
||||
int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
|
||||
#endif
|
||||
|
||||
#if defined(LTC_MECC_FP)
|
||||
/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
|
||||
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
/* functions for saving/loading/freeing/adding to fixed point cache */
|
||||
int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
|
||||
int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen);
|
||||
void ltc_ecc_fp_free(void);
|
||||
int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock);
|
||||
|
||||
/* lock/unlock all points currently in fixed point cache */
|
||||
void ltc_ecc_fp_tablelock(int lock);
|
||||
#endif
|
||||
|
||||
/* R = kG */
|
||||
int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
#ifdef LTC_ECC_SHAMIR
|
||||
/* kA*A + kB*B = C */
|
||||
int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C,
|
||||
void *modulus);
|
||||
|
||||
#ifdef LTC_MECC_FP
|
||||
/* Shamir's trick with optimized point multiplication using fixed point cache */
|
||||
int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C, void *modulus);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* map P to affine from projective */
|
||||
int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MDSA
|
||||
|
||||
/* Max diff between group and modulus size in bytes */
|
||||
#define LTC_MDSA_DELTA 512
|
||||
|
||||
/* Max DSA group size in bytes (default allows 4k-bit groups) */
|
||||
#define LTC_MDSA_MAX_GROUP 512
|
||||
|
||||
/** DSA key structure */
|
||||
typedef struct {
|
||||
/** The key type, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
|
||||
/** The order of the sub-group used in octets */
|
||||
int qord;
|
||||
|
||||
/** The generator */
|
||||
void *g;
|
||||
|
||||
/** The prime used to generate the sub-group */
|
||||
void *q;
|
||||
|
||||
/** The large prime that generats the field the contains the sub-group */
|
||||
void *p;
|
||||
|
||||
/** The private key */
|
||||
void *x;
|
||||
|
||||
/** The public key */
|
||||
void *y;
|
||||
} dsa_key;
|
||||
|
||||
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
|
||||
void dsa_free(dsa_key *key);
|
||||
|
||||
int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
|
||||
void *r, void *s,
|
||||
prng_state *prng, int wprng, dsa_key *key);
|
||||
|
||||
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, dsa_key *key);
|
||||
|
||||
int dsa_verify_hash_raw( void *r, void *s,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dsa_key *key);
|
||||
|
||||
int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dsa_key *key);
|
||||
|
||||
int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
dsa_key *key);
|
||||
|
||||
int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
dsa_key *key);
|
||||
|
||||
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
|
||||
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
|
||||
int dsa_verify_key(dsa_key *key, int *stat);
|
||||
|
||||
int dsa_shared_secret(void *private_key, void *base,
|
||||
dsa_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DER
|
||||
/* DER handling */
|
||||
|
||||
enum {
|
||||
LTC_ASN1_EOL,
|
||||
LTC_ASN1_BOOLEAN,
|
||||
LTC_ASN1_INTEGER,
|
||||
LTC_ASN1_SHORT_INTEGER,
|
||||
LTC_ASN1_BIT_STRING,
|
||||
LTC_ASN1_OCTET_STRING,
|
||||
LTC_ASN1_NULL,
|
||||
LTC_ASN1_OBJECT_IDENTIFIER,
|
||||
LTC_ASN1_IA5_STRING,
|
||||
LTC_ASN1_PRINTABLE_STRING,
|
||||
LTC_ASN1_UTF8_STRING,
|
||||
LTC_ASN1_UTCTIME,
|
||||
LTC_ASN1_CHOICE,
|
||||
LTC_ASN1_SEQUENCE,
|
||||
LTC_ASN1_SET,
|
||||
LTC_ASN1_SETOF
|
||||
};
|
||||
|
||||
/** A LTC ASN.1 list type */
|
||||
typedef struct ltc_asn1_list_ {
|
||||
/** The LTC ASN.1 enumerated type identifier */
|
||||
int type;
|
||||
/** The data to encode or place for decoding */
|
||||
void *data;
|
||||
/** The size of the input or resulting output */
|
||||
unsigned long size;
|
||||
/** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
|
||||
int used;
|
||||
/** prev/next entry in the list */
|
||||
struct ltc_asn1_list_ *prev, *next, *child, *parent;
|
||||
} ltc_asn1_list;
|
||||
|
||||
#define LTC_SET_ASN1(list, index, Type, Data, Size) \
|
||||
do { \
|
||||
int LTC_MACRO_temp = (index); \
|
||||
ltc_asn1_list *LTC_MACRO_list = (list); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
|
||||
} while (0);
|
||||
|
||||
/* SEQUENCE */
|
||||
int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int type_of);
|
||||
|
||||
#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
|
||||
|
||||
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
|
||||
ltc_asn1_list *list, unsigned long outlen, int ordered);
|
||||
|
||||
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
|
||||
|
||||
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned long *outlen);
|
||||
|
||||
/* SET */
|
||||
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
|
||||
#define der_length_set der_length_sequence
|
||||
int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* VA list handy helpers with triplets of <type, size, data> */
|
||||
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
|
||||
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
|
||||
|
||||
/* FLEXI DECODER handle unknown list decoder */
|
||||
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
|
||||
void der_free_sequence_flexi(ltc_asn1_list *list);
|
||||
void der_sequence_free(ltc_asn1_list *in);
|
||||
|
||||
/* BOOLEAN */
|
||||
int der_length_boolean(unsigned long *outlen);
|
||||
int der_encode_boolean(int in,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_boolean(const unsigned char *in, unsigned long inlen,
|
||||
int *out);
|
||||
/* INTEGER */
|
||||
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num);
|
||||
int der_length_integer(void *num, unsigned long *len);
|
||||
|
||||
/* INTEGER -- handy for 0..2^32-1 values */
|
||||
int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);
|
||||
int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);
|
||||
int der_length_short_integer(unsigned long num, unsigned long *outlen);
|
||||
|
||||
/* BIT STRING */
|
||||
int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
|
||||
|
||||
/* OCTET STRING */
|
||||
int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
/* OBJECT IDENTIFIER */
|
||||
int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
|
||||
unsigned long *words, unsigned long *outlen);
|
||||
int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen);
|
||||
unsigned long der_object_identifier_bits(unsigned long x);
|
||||
|
||||
/* IA5 STRING */
|
||||
int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
int der_ia5_char_encode(int c);
|
||||
int der_ia5_value_decode(int v);
|
||||
|
||||
/* Printable STRING */
|
||||
int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
int der_printable_char_encode(int c);
|
||||
int der_printable_value_decode(int v);
|
||||
|
||||
/* UTF-8 */
|
||||
#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR)
|
||||
#include <wchar.h>
|
||||
#else
|
||||
typedef ulong32 wchar_t;
|
||||
#endif
|
||||
|
||||
int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
|
||||
wchar_t *out, unsigned long *outlen);
|
||||
unsigned long der_utf8_charsize(const wchar_t c);
|
||||
int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
|
||||
/* CHOICE */
|
||||
int der_decode_choice(const unsigned char *in, unsigned long *inlen,
|
||||
ltc_asn1_list *list, unsigned long outlen);
|
||||
|
||||
/* UTCTime */
|
||||
typedef struct {
|
||||
unsigned YY, /* year */
|
||||
MM, /* month */
|
||||
DD, /* day */
|
||||
hh, /* hour */
|
||||
mm, /* minute */
|
||||
ss, /* second */
|
||||
off_dir, /* timezone offset direction 0 == +, 1 == - */
|
||||
off_hh, /* timezone offset hours */
|
||||
off_mm; /* timezone offset minutes */
|
||||
} ltc_utctime;
|
||||
|
||||
int der_encode_utctime(ltc_utctime *utctime,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
|
||||
ltc_utctime *out);
|
||||
|
||||
int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */
|
||||
/* $Revision: 1.81 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
89
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_pkcs.h
vendored
Normal file
89
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_pkcs.h
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/* LTC_PKCS Header Info */
|
||||
|
||||
/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */
|
||||
#ifdef LTC_PKCS_1
|
||||
|
||||
enum ltc_pkcs_1_v1_5_blocks
|
||||
{
|
||||
LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */
|
||||
LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */
|
||||
};
|
||||
|
||||
enum ltc_pkcs_1_paddings
|
||||
{
|
||||
LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
|
||||
LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */
|
||||
LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */
|
||||
};
|
||||
|
||||
int pkcs_1_mgf1( int hash_idx,
|
||||
const unsigned char *seed, unsigned long seedlen,
|
||||
unsigned char *mask, unsigned long masklen);
|
||||
|
||||
int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
|
||||
int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
|
||||
|
||||
/* *** v1.5 padding */
|
||||
int pkcs_1_v1_5_encode(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
int block_type,
|
||||
unsigned long modulus_bitlen,
|
||||
prng_state *prng,
|
||||
int prng_idx,
|
||||
unsigned char *out,
|
||||
unsigned long *outlen);
|
||||
|
||||
int pkcs_1_v1_5_decode(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
int block_type,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned char *out,
|
||||
unsigned long *outlen,
|
||||
int *is_valid);
|
||||
|
||||
/* *** v2.1 padding */
|
||||
int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
unsigned long modulus_bitlen, prng_state *prng,
|
||||
int prng_idx, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
unsigned long modulus_bitlen, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
int *res);
|
||||
|
||||
int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
|
||||
unsigned long saltlen, prng_state *prng,
|
||||
int prng_idx, int hash_idx,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
|
||||
const unsigned char *sig, unsigned long siglen,
|
||||
unsigned long saltlen, int hash_idx,
|
||||
unsigned long modulus_bitlen, int *res);
|
||||
|
||||
#endif /* LTC_PKCS_1 */
|
||||
|
||||
/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */
|
||||
#ifdef LTC_PKCS_5
|
||||
|
||||
/* Algorithm #1 (old) */
|
||||
int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
|
||||
const unsigned char *salt,
|
||||
int iteration_count, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* Algorithm #2 (new) */
|
||||
int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
|
||||
const unsigned char *salt, unsigned long salt_len,
|
||||
int iteration_count, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
#endif /* LTC_PKCS_5 */
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pkcs.h,v $ */
|
||||
/* $Revision: 1.8 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
199
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_prng.h
vendored
Normal file
199
vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_prng.h
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
/* ---- PRNG Stuff ---- */
|
||||
#ifdef LTC_YARROW
|
||||
struct yarrow_prng {
|
||||
int cipher, hash;
|
||||
unsigned char pool[MAXBLOCKSIZE];
|
||||
symmetric_CTR ctr;
|
||||
LTC_MUTEX_TYPE(prng_lock)
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC4
|
||||
struct rc4_prng {
|
||||
int x, y;
|
||||
unsigned char buf[256];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_FORTUNA
|
||||
struct fortuna_prng {
|
||||
hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */
|
||||
|
||||
symmetric_key skey;
|
||||
|
||||
unsigned char K[32], /* the current key */
|
||||
IV[16]; /* IV for CTR mode */
|
||||
|
||||
unsigned long pool_idx, /* current pool we will add to */
|
||||
pool0_len, /* length of 0'th pool */
|
||||
wd;
|
||||
|
||||
ulong64 reset_cnt; /* number of times we have reset */
|
||||
LTC_MUTEX_TYPE(prng_lock)
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SOBER128
|
||||
struct sober128_prng {
|
||||
ulong32 R[17], /* Working storage for the shift register */
|
||||
initR[17], /* saved register contents */
|
||||
konst, /* key dependent constant */
|
||||
sbuf; /* partial word encryption buffer */
|
||||
|
||||
int nbuf, /* number of part-word stream bits buffered */
|
||||
flag, /* first add_entropy call or not? */
|
||||
set; /* did we call add_entropy to set key? */
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Prng_state {
|
||||
char dummy[1];
|
||||
#ifdef LTC_YARROW
|
||||
struct yarrow_prng yarrow;
|
||||
#endif
|
||||
#ifdef LTC_RC4
|
||||
struct rc4_prng rc4;
|
||||
#endif
|
||||
#ifdef LTC_FORTUNA
|
||||
struct fortuna_prng fortuna;
|
||||
#endif
|
||||
#ifdef LTC_SOBER128
|
||||
struct sober128_prng sober128;
|
||||
#endif
|
||||
} prng_state;
|
||||
|
||||
/** PRNG descriptor */
|
||||
extern struct ltc_prng_descriptor {
|
||||
/** Name of the PRNG */
|
||||
char *name;
|
||||
/** size in bytes of exported state */
|
||||
int export_size;
|
||||
/** Start a PRNG state
|
||||
@param prng [out] The state to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*start)(prng_state *prng);
|
||||
/** Add entropy to the PRNG
|
||||
@param in The entropy
|
||||
@param inlen Length of the entropy (octets)\
|
||||
@param prng The PRNG state
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
/** Ready a PRNG state to read from
|
||||
@param prng The PRNG state to ready
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ready)(prng_state *prng);
|
||||
/** Read from the PRNG
|
||||
@param out [out] Where to store the data
|
||||
@param outlen Length of data desired (octets)
|
||||
@param prng The PRNG state to read from
|
||||
@return Number of octets read
|
||||
*/
|
||||
unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
/** Terminate a PRNG state
|
||||
@param prng The PRNG state to terminate
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*done)(prng_state *prng);
|
||||
/** Export a PRNG state
|
||||
@param out [out] The destination for the state
|
||||
@param outlen [in/out] The max size and resulting size of the PRNG state
|
||||
@param prng The PRNG to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
/** Import a PRNG state
|
||||
@param in The data to import
|
||||
@param inlen The length of the data to import (octets)
|
||||
@param prng The PRNG to initialize/import
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
/** Self-test the PRNG
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
} prng_descriptor[];
|
||||
|
||||
#ifdef LTC_YARROW
|
||||
int yarrow_start(prng_state *prng);
|
||||
int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int yarrow_ready(prng_state *prng);
|
||||
unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int yarrow_done(prng_state *prng);
|
||||
int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int yarrow_test(void);
|
||||
extern const struct ltc_prng_descriptor yarrow_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_FORTUNA
|
||||
int fortuna_start(prng_state *prng);
|
||||
int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int fortuna_ready(prng_state *prng);
|
||||
unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int fortuna_done(prng_state *prng);
|
||||
int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int fortuna_test(void);
|
||||
extern const struct ltc_prng_descriptor fortuna_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC4
|
||||
int rc4_start(prng_state *prng);
|
||||
int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int rc4_ready(prng_state *prng);
|
||||
unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int rc4_done(prng_state *prng);
|
||||
int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int rc4_test(void);
|
||||
extern const struct ltc_prng_descriptor rc4_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SPRNG
|
||||
int sprng_start(prng_state *prng);
|
||||
int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sprng_ready(prng_state *prng);
|
||||
unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int sprng_done(prng_state *prng);
|
||||
int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sprng_test(void);
|
||||
extern const struct ltc_prng_descriptor sprng_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SOBER128
|
||||
int sober128_start(prng_state *prng);
|
||||
int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sober128_ready(prng_state *prng);
|
||||
unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int sober128_done(prng_state *prng);
|
||||
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sober128_test(void);
|
||||
extern const struct ltc_prng_descriptor sober128_desc;
|
||||
#endif
|
||||
|
||||
int find_prng(const char *name);
|
||||
int register_prng(const struct ltc_prng_descriptor *prng);
|
||||
int unregister_prng(const struct ltc_prng_descriptor *prng);
|
||||
int prng_is_valid(int idx);
|
||||
LTC_MUTEX_PROTO(ltc_prng_mutex)
|
||||
|
||||
/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
|
||||
* might not work on all platforms as planned
|
||||
*/
|
||||
unsigned long rng_get_bytes(unsigned char *out,
|
||||
unsigned long outlen,
|
||||
void (*callback)(void));
|
||||
|
||||
int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */
|
||||
/* $Revision: 1.9 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
483
vendor/stormlib-9/src/libtomcrypt/src/math/ltm_desc.c
vendored
Normal file
483
vendor/stormlib-9/src/libtomcrypt/src/math/ltm_desc.c
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
|
||||
#define DESC_DEF_ONLY
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
#ifdef LTM_DESC
|
||||
|
||||
#include "../../../libtommath/tommath.h"
|
||||
|
||||
static const struct {
|
||||
int mpi_code, ltc_code;
|
||||
} mpi_to_ltc_codes[] = {
|
||||
{ MP_OKAY , CRYPT_OK},
|
||||
{ MP_MEM , CRYPT_MEM},
|
||||
{ MP_VAL , CRYPT_INVALID_ARG},
|
||||
};
|
||||
|
||||
/**
|
||||
Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
|
||||
@param err The error to convert
|
||||
@return The equivalent LTC error code or CRYPT_ERROR if none found
|
||||
*/
|
||||
static int mpi_to_ltc_error(int err)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
|
||||
if (err == mpi_to_ltc_codes[x].mpi_code) {
|
||||
return mpi_to_ltc_codes[x].ltc_code;
|
||||
}
|
||||
}
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
static int init(void **a)
|
||||
{
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(a != NULL);
|
||||
|
||||
*a = XCALLOC(1, sizeof(mp_int));
|
||||
if (*a == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {
|
||||
XFREE(*a);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void deinit(void *a)
|
||||
{
|
||||
LTC_ARGCHKVD(a != NULL);
|
||||
mp_clear(a);
|
||||
XFREE(a);
|
||||
}
|
||||
|
||||
static int neg(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_neg(a, b));
|
||||
}
|
||||
|
||||
static int copy(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_copy(a, b));
|
||||
}
|
||||
|
||||
static int init_copy(void **a, void *b)
|
||||
{
|
||||
if (init(a) != CRYPT_OK) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
return copy(b, *a);
|
||||
}
|
||||
|
||||
/* ---- trivial ---- */
|
||||
static int set_int(void *a, unsigned long b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mpi_to_ltc_error(mp_set_int(a, b));
|
||||
}
|
||||
|
||||
static unsigned long get_int(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_get_int(a);
|
||||
}
|
||||
|
||||
static unsigned long get_digit(void *a, int n)
|
||||
{
|
||||
mp_int *A;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
A = a;
|
||||
return (n >= A->used || n < 0) ? 0 : A->dp[n];
|
||||
}
|
||||
|
||||
static int get_digit_count(void *a)
|
||||
{
|
||||
mp_int *A;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
A = a;
|
||||
return A->used;
|
||||
}
|
||||
|
||||
static int compare(void *a, void *b)
|
||||
{
|
||||
int ret;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
ret = mp_cmp(a, b);
|
||||
switch (ret) {
|
||||
case MP_LT: return LTC_MP_LT;
|
||||
case MP_EQ: return LTC_MP_EQ;
|
||||
case MP_GT: return LTC_MP_GT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_d(void *a, unsigned long b)
|
||||
{
|
||||
int ret;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
ret = mp_cmp_d(a, b);
|
||||
switch (ret) {
|
||||
case MP_LT: return LTC_MP_LT;
|
||||
case MP_EQ: return LTC_MP_EQ;
|
||||
case MP_GT: return LTC_MP_GT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count_bits(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_count_bits(a);
|
||||
}
|
||||
|
||||
static int count_lsb_bits(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_cnt_lsb(a);
|
||||
}
|
||||
|
||||
|
||||
static int twoexpt(void *a, int n)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mpi_to_ltc_error(mp_2expt(a, n));
|
||||
}
|
||||
|
||||
/* ---- conversions ---- */
|
||||
|
||||
/* read ascii string */
|
||||
static int read_radix(void *a, const char *b, int radix)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_read_radix(a, b, radix));
|
||||
}
|
||||
|
||||
/* write one */
|
||||
static int write_radix(void *a, char *b, int radix)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_toradix(a, b, radix));
|
||||
}
|
||||
|
||||
/* get size as unsigned char string */
|
||||
static unsigned long unsigned_size(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_unsigned_bin_size(a);
|
||||
}
|
||||
|
||||
/* store */
|
||||
static int unsigned_write(void *a, unsigned char *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
|
||||
}
|
||||
|
||||
/* read */
|
||||
static int unsigned_read(void *a, unsigned char *b, unsigned long len)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));
|
||||
}
|
||||
|
||||
/* add */
|
||||
static int add(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_add(a, b, c));
|
||||
}
|
||||
|
||||
static int addi(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_add_d(a, b, c));
|
||||
}
|
||||
|
||||
/* sub */
|
||||
static int sub(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sub(a, b, c));
|
||||
}
|
||||
|
||||
static int subi(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sub_d(a, b, c));
|
||||
}
|
||||
|
||||
/* mul */
|
||||
static int mul(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_mul(a, b, c));
|
||||
}
|
||||
|
||||
static int muli(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_mul_d(a, b, c));
|
||||
}
|
||||
|
||||
/* sqr */
|
||||
static int sqr(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_sqr(a, b));
|
||||
}
|
||||
|
||||
/* div */
|
||||
static int divide(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_div(a, b, c, d));
|
||||
}
|
||||
|
||||
static int div_2(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_div_2(a, b));
|
||||
}
|
||||
|
||||
/* modi */
|
||||
static int modi(void *a, unsigned long b, unsigned long *c)
|
||||
{
|
||||
mp_digit tmp;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
|
||||
if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
*c = tmp;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* gcd */
|
||||
static int gcd(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_gcd(a, b, c));
|
||||
}
|
||||
|
||||
/* lcm */
|
||||
static int lcm(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_lcm(a, b, c));
|
||||
}
|
||||
|
||||
static int mulmod(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
LTC_ARGCHK(d != NULL);
|
||||
return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
|
||||
}
|
||||
|
||||
static int sqrmod(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sqrmod(a,b,c));
|
||||
}
|
||||
|
||||
/* invmod */
|
||||
static int invmod(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_invmod(a, b, c));
|
||||
}
|
||||
|
||||
/* setup */
|
||||
static int montgomery_setup(void *a, void **b)
|
||||
{
|
||||
int err;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
*b = XCALLOC(1, sizeof(mp_digit));
|
||||
if (*b == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {
|
||||
XFREE(*b);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get normalization value */
|
||||
static int montgomery_normalization(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));
|
||||
}
|
||||
|
||||
/* reduce */
|
||||
static int montgomery_reduce(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
static void montgomery_deinit(void *a)
|
||||
{
|
||||
XFREE(a);
|
||||
}
|
||||
|
||||
static int exptmod(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
LTC_ARGCHK(d != NULL);
|
||||
return mpi_to_ltc_error(mp_exptmod(a,b,c,d));
|
||||
}
|
||||
|
||||
static int isprime(void *a, int *b)
|
||||
{
|
||||
int err;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
err = mpi_to_ltc_error(mp_prime_is_prime(a, 8, b));
|
||||
*b = (*b == MP_YES) ? LTC_MP_YES : LTC_MP_NO;
|
||||
return err;
|
||||
}
|
||||
|
||||
const ltc_math_descriptor ltm_desc = {
|
||||
|
||||
"LibTomMath",
|
||||
(int)DIGIT_BIT,
|
||||
|
||||
&init,
|
||||
&init_copy,
|
||||
&deinit,
|
||||
|
||||
&neg,
|
||||
©,
|
||||
|
||||
&set_int,
|
||||
&get_int,
|
||||
&get_digit,
|
||||
&get_digit_count,
|
||||
&compare,
|
||||
&compare_d,
|
||||
&count_bits,
|
||||
&count_lsb_bits,
|
||||
&twoexpt,
|
||||
|
||||
&read_radix,
|
||||
&write_radix,
|
||||
&unsigned_size,
|
||||
&unsigned_write,
|
||||
&unsigned_read,
|
||||
|
||||
&add,
|
||||
&addi,
|
||||
&sub,
|
||||
&subi,
|
||||
&mul,
|
||||
&muli,
|
||||
&sqr,
|
||||
÷,
|
||||
&div_2,
|
||||
&modi,
|
||||
&gcd,
|
||||
&lcm,
|
||||
|
||||
&mulmod,
|
||||
&sqrmod,
|
||||
&invmod,
|
||||
|
||||
&montgomery_setup,
|
||||
&montgomery_normalization,
|
||||
&montgomery_reduce,
|
||||
&montgomery_deinit,
|
||||
|
||||
&exptmod,
|
||||
&isprime,
|
||||
|
||||
#ifdef LTC_MECC
|
||||
#ifdef LTC_MECC_FP
|
||||
<c_ecc_fp_mulmod,
|
||||
#else
|
||||
<c_ecc_mulmod,
|
||||
#endif
|
||||
<c_ecc_projective_add_point,
|
||||
<c_ecc_projective_dbl_point,
|
||||
<c_ecc_map,
|
||||
#ifdef LTC_ECC_SHAMIR
|
||||
#ifdef LTC_MECC_FP
|
||||
<c_ecc_fp_mul2add,
|
||||
#else
|
||||
<c_ecc_mul2add,
|
||||
#endif /* LTC_MECC_FP */
|
||||
#else
|
||||
NULL,
|
||||
#endif /* LTC_ECC_SHAMIR */
|
||||
#else
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
#endif /* LTC_MECC */
|
||||
|
||||
#ifdef LTC_MRSA
|
||||
&rsa_make_key,
|
||||
&rsa_exptmod,
|
||||
#else
|
||||
NULL, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/math/ltm_desc.c,v $ */
|
||||
/* $Revision: 1.31 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
61
vendor/stormlib-9/src/libtomcrypt/src/math/multi.c
vendored
Normal file
61
vendor/stormlib-9/src/libtomcrypt/src/math/multi.c
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
#ifdef MPI
|
||||
#include <stdarg.h>
|
||||
|
||||
int ltc_init_multi(void **a, ...)
|
||||
{
|
||||
void **cur = a;
|
||||
int np = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, a);
|
||||
while (cur != NULL) {
|
||||
if (mp_init(cur) != CRYPT_OK) {
|
||||
/* failed */
|
||||
va_list clean_list;
|
||||
|
||||
va_start(clean_list, a);
|
||||
cur = a;
|
||||
while (np--) {
|
||||
mp_clear(*cur);
|
||||
cur = va_arg(clean_list, void**);
|
||||
}
|
||||
va_end(clean_list);
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
++np;
|
||||
cur = va_arg(args, void**);
|
||||
}
|
||||
va_end(args);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
void ltc_deinit_multi(void *a, ...)
|
||||
{
|
||||
void *cur = a;
|
||||
va_list args;
|
||||
|
||||
va_start(args, a);
|
||||
while (cur != NULL) {
|
||||
mp_clear(cur);
|
||||
cur = va_arg(args, void *);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/math/multi.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:23 $ */
|
||||
87
vendor/stormlib-9/src/libtomcrypt/src/math/rand_prime.c
vendored
Normal file
87
vendor/stormlib-9/src/libtomcrypt/src/math/rand_prime.c
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file rand_prime.c
|
||||
Generate a random prime, Tom St Denis
|
||||
*/
|
||||
|
||||
#define USE_BBS 1
|
||||
|
||||
int rand_prime(void *N, long len, prng_state *prng, int wprng)
|
||||
{
|
||||
int err, res, type;
|
||||
unsigned char *buf;
|
||||
|
||||
LTC_ARGCHK(N != NULL);
|
||||
|
||||
/* get type */
|
||||
if (len < 0) {
|
||||
type = USE_BBS;
|
||||
len = -len;
|
||||
} else {
|
||||
type = 0;
|
||||
}
|
||||
|
||||
/* allow sizes between 2 and 512 bytes for a prime size */
|
||||
if (len < 2 || len > 512) {
|
||||
return CRYPT_INVALID_PRIME_SIZE;
|
||||
}
|
||||
|
||||
/* valid PRNG? Better be! */
|
||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* allocate buffer to work with */
|
||||
buf = XCALLOC(1, len);
|
||||
if (buf == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
do {
|
||||
/* generate value */
|
||||
if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) {
|
||||
XFREE(buf);
|
||||
return CRYPT_ERROR_READPRNG;
|
||||
}
|
||||
|
||||
/* munge bits */
|
||||
buf[0] |= 0x80 | 0x40;
|
||||
buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
|
||||
|
||||
/* load value */
|
||||
if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
|
||||
XFREE(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* test */
|
||||
if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) {
|
||||
XFREE(buf);
|
||||
return err;
|
||||
}
|
||||
} while (res == LTC_MP_NO);
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(buf, len);
|
||||
#endif
|
||||
|
||||
XFREE(buf);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */
|
||||
/* $Revision: 1.7 $ */
|
||||
/* $Date: 2006/12/28 01:27:23 $ */
|
||||
104
vendor/stormlib-9/src/libtomcrypt/src/misc/base64_decode.c
vendored
Normal file
104
vendor/stormlib-9/src/libtomcrypt/src/misc/base64_decode.c
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file base64_decode.c
|
||||
Compliant base64 code donated by Wayne Scott (wscott@bitmover.com)
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_BASE64
|
||||
|
||||
static const unsigned char map[256] = {
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
|
||||
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
|
||||
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
|
||||
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255 };
|
||||
|
||||
/**
|
||||
base64 decode a block of memory
|
||||
@param in The base64 data to decode
|
||||
@param inlen The length of the base64 data
|
||||
@param out [out] The destination of the binary decoded data
|
||||
@param outlen [in/out] The max size and resulting size of the decoded data
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int base64_decode(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
unsigned long t, x, y, z;
|
||||
unsigned char c;
|
||||
int g;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
g = 3;
|
||||
for (x = y = z = t = 0; x < inlen; x++) {
|
||||
c = map[in[x]&0xFF];
|
||||
if (c == 255) continue;
|
||||
/* the final = symbols are read and used to trim the remaining bytes */
|
||||
if (c == 254) {
|
||||
c = 0;
|
||||
/* prevent g < 0 which would potentially allow an overflow later */
|
||||
if (--g < 0) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
} else if (g != 3) {
|
||||
/* we only allow = to be at the end */
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
t = (t<<6)|c;
|
||||
|
||||
if (++y == 4) {
|
||||
if (z + g > *outlen) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
out[z++] = (unsigned char)((t>>16)&255);
|
||||
if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
|
||||
if (g > 2) out[z++] = (unsigned char)(t&255);
|
||||
y = t = 0;
|
||||
}
|
||||
}
|
||||
if (y != 0) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
*outlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/base64/base64_decode.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
30
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_argchk.c
vendored
Normal file
30
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_argchk.c
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
#include <signal.h>
|
||||
|
||||
/**
|
||||
@file crypt_argchk.c
|
||||
Perform argument checking, Tom St Denis
|
||||
*/
|
||||
|
||||
#if (ARGTYPE == 0)
|
||||
void crypt_argchk(char *v, char *s, int d)
|
||||
{
|
||||
fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n",
|
||||
v, d, s);
|
||||
(void)raise(SIGABRT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
40
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_find_hash.c
vendored
Normal file
40
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_find_hash.c
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_find_hash.c
|
||||
Find a hash, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Find a registered hash by name
|
||||
@param name The name of the hash to look for
|
||||
@return >= 0 if found, -1 if not present
|
||||
*/
|
||||
int find_hash(const char *name)
|
||||
{
|
||||
int x;
|
||||
LTC_ARGCHK(name != NULL);
|
||||
LTC_MUTEX_LOCK(<c_hash_mutex);
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) {
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_hash.c,v $ */
|
||||
/* $Revision: 1.7 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
41
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_find_prng.c
vendored
Normal file
41
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_find_prng.c
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_find_prng.c
|
||||
Find a PRNG, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Find a registered PRNG by name
|
||||
@param name The name of the PRNG to look for
|
||||
@return >= 0 if found, -1 if not present
|
||||
*/
|
||||
int find_prng(const char *name)
|
||||
{
|
||||
int x;
|
||||
LTC_ARGCHK(name != NULL);
|
||||
LTC_MUTEX_LOCK(<c_prng_mutex);
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) {
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_find_prng.c,v $ */
|
||||
/* $Revision: 1.7 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
27
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_hash_descriptor.c
vendored
Normal file
27
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_hash_descriptor.c
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_hash_descriptor.c
|
||||
Stores the hash descriptor table, Tom St Denis
|
||||
*/
|
||||
|
||||
struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = {
|
||||
{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
LTC_MUTEX_GLOBAL(ltc_hash_mutex)
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c,v $ */
|
||||
/* $Revision: 1.10 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
36
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_hash_is_valid.c
vendored
Normal file
36
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_hash_is_valid.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_hash_is_valid.c
|
||||
Determine if hash is valid, Tom St Denis
|
||||
*/
|
||||
|
||||
/*
|
||||
Test if a hash index is valid
|
||||
@param idx The index of the hash to search for
|
||||
@return CRYPT_OK if valid
|
||||
*/
|
||||
int hash_is_valid(int idx)
|
||||
{
|
||||
LTC_MUTEX_LOCK(<c_hash_mutex);
|
||||
if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return CRYPT_INVALID_HASH;
|
||||
}
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
43
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_libc.c
vendored
Normal file
43
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_libc.c
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*****************************************************************************/
|
||||
/* crypt_libc.c Copyright (c) Ladislav Zezula 2010 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 05.05.10 1.00 Lad The first version of crypt_libc.c */
|
||||
/*****************************************************************************/
|
||||
|
||||
// LibTomCrypt header
|
||||
#include <stdlib.h>
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
LTC_EXPORT void * LTC_CALL LibTomMalloc(size_t n)
|
||||
{
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
LTC_EXPORT void * LTC_CALL LibTomCalloc(size_t n, size_t s)
|
||||
{
|
||||
return calloc(n, s);
|
||||
}
|
||||
|
||||
LTC_EXPORT void * LTC_CALL LibTomRealloc(void *p, size_t n)
|
||||
{
|
||||
return realloc(p, n);
|
||||
}
|
||||
|
||||
LTC_EXPORT void LTC_CALL LibTomFree(void * p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
LTC_EXPORT clock_t LTC_CALL LibTomClock(void)
|
||||
{
|
||||
return clock();
|
||||
}
|
||||
|
||||
LTC_EXPORT void LTC_CALL LibTomQsort(void *base, size_t nmemb, size_t size, int(LTC_CALL * compar)(const void *, const void *))
|
||||
{
|
||||
qsort(base, nmemb, size, compar);
|
||||
}
|
||||
13
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
vendored
Normal file
13
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
ltc_math_descriptor ltc_mp = {0};
|
||||
26
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_prng_descriptor.c
vendored
Normal file
26
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_prng_descriptor.c
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_prng_descriptor.c
|
||||
Stores the PRNG descriptors, Tom St Denis
|
||||
*/
|
||||
struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = {
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
LTC_MUTEX_GLOBAL(ltc_prng_mutex)
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c,v $ */
|
||||
/* $Revision: 1.8 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
36
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_prng_is_valid.c
vendored
Normal file
36
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_prng_is_valid.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_prng_is_valid.c
|
||||
Determine if PRNG is valid, Tom St Denis
|
||||
*/
|
||||
|
||||
/*
|
||||
Test if a PRNG index is valid
|
||||
@param idx The index of the PRNG to search for
|
||||
@return CRYPT_OK if valid
|
||||
*/
|
||||
int prng_is_valid(int idx)
|
||||
{
|
||||
LTC_MUTEX_LOCK(<c_prng_mutex);
|
||||
if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return CRYPT_INVALID_PRNG;
|
||||
}
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
54
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_register_hash.c
vendored
Normal file
54
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_register_hash.c
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_register_hash.c
|
||||
Register a HASH, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Register a hash with the descriptor table
|
||||
@param hash The hash you wish to register
|
||||
@return value >= 0 if successfully added (or already present), -1 if unsuccessful
|
||||
*/
|
||||
int register_hash(const struct ltc_hash_descriptor *hash)
|
||||
{
|
||||
int x;
|
||||
|
||||
LTC_ARGCHK(hash != NULL);
|
||||
|
||||
/* is it already registered? */
|
||||
LTC_MUTEX_LOCK(<c_hash_mutex);
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) {
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/* find a blank spot */
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if (hash_descriptor[x].name == NULL) {
|
||||
XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor));
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/* no spot */
|
||||
LTC_MUTEX_UNLOCK(<c_hash_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_hash.c,v $ */
|
||||
/* $Revision: 1.7 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
54
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_register_prng.c
vendored
Normal file
54
vendor/stormlib-9/src/libtomcrypt/src/misc/crypt_register_prng.c
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file crypt_register_prng.c
|
||||
Register a PRNG, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Register a PRNG with the descriptor table
|
||||
@param prng The PRNG you wish to register
|
||||
@return value >= 0 if successfully added (or already present), -1 if unsuccessful
|
||||
*/
|
||||
int register_prng(const struct ltc_prng_descriptor *prng)
|
||||
{
|
||||
int x;
|
||||
|
||||
LTC_ARGCHK(prng != NULL);
|
||||
|
||||
/* is it already registered? */
|
||||
LTC_MUTEX_LOCK(<c_prng_mutex);
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) {
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/* find a blank spot */
|
||||
for (x = 0; x < TAB_SIZE; x++) {
|
||||
if (prng_descriptor[x].name == NULL) {
|
||||
XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor));
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/* no spot */
|
||||
LTC_MUTEX_UNLOCK(<c_prng_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_register_prng.c,v $ */
|
||||
/* $Revision: 1.8 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
34
vendor/stormlib-9/src/libtomcrypt/src/misc/zeromem.c
vendored
Normal file
34
vendor/stormlib-9/src/libtomcrypt/src/misc/zeromem.c
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file zeromem.c
|
||||
Zero a block of memory, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Zero a block of memory
|
||||
@param out The destination of the area to zero
|
||||
@param outlen The length of the area to zero (octets)
|
||||
*/
|
||||
void zeromem(void *out, size_t outlen)
|
||||
{
|
||||
unsigned char *mem = out;
|
||||
LTC_ARGCHKVD(out != NULL);
|
||||
while (outlen-- > 0) {
|
||||
*mem++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */
|
||||
/* $Revision: 1.7 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
102
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
vendored
Normal file
102
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_bit_string.c
|
||||
ASN.1 DER, encode a BIT STRING, Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Store a BIT STRING
|
||||
@param in The DER encoded BIT STRING
|
||||
@param inlen The size of the DER BIT STRING
|
||||
@param out [out] The array of bits stored (one per char)
|
||||
@param outlen [in/out] The number of bits stored
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
unsigned long dlen, blen, x, y;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* packet must be at least 4 bytes */
|
||||
if (inlen < 4) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* check for 0x03 */
|
||||
if ((in[0]&0x1F) != 0x03) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* offset in the data */
|
||||
x = 1;
|
||||
|
||||
/* get the length of the data */
|
||||
if (in[x] & 0x80) {
|
||||
/* long format get number of length bytes */
|
||||
y = in[x++] & 0x7F;
|
||||
|
||||
/* invalid if 0 or > 2 */
|
||||
if (y == 0 || y > 2) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* read the data len */
|
||||
dlen = 0;
|
||||
while (y--) {
|
||||
dlen = (dlen << 8) | (unsigned long)in[x++];
|
||||
}
|
||||
} else {
|
||||
/* short format */
|
||||
dlen = in[x++] & 0x7F;
|
||||
}
|
||||
|
||||
/* is the data len too long or too short? */
|
||||
if ((dlen == 0) || (dlen + x > inlen)) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* get padding count */
|
||||
blen = ((dlen - 1) << 3) - (in[x++] & 7);
|
||||
|
||||
/* too many bits? */
|
||||
if (blen > *outlen) {
|
||||
*outlen = blen;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* decode/store the bits */
|
||||
for (y = 0; y < blen; y++) {
|
||||
out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
|
||||
if ((y & 7) == 7) {
|
||||
++x;
|
||||
}
|
||||
}
|
||||
|
||||
/* we done */
|
||||
*outlen = blen;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
47
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
vendored
Normal file
47
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_boolean.c
|
||||
ASN.1 DER, decode a BOOLEAN, Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Read a BOOLEAN
|
||||
@param in The destination for the DER encoded BOOLEAN
|
||||
@param inlen The size of the DER BOOLEAN
|
||||
@param out [out] The boolean to decode
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_boolean(const unsigned char *in, unsigned long inlen,
|
||||
int *out)
|
||||
{
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
*out = (in[2]==0xFF) ? 1 : 0;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */
|
||||
/* $Revision: 1.2 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
182
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_choice.c
vendored
Normal file
182
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_choice.c
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_choice.c
|
||||
ASN.1 DER, decode a CHOICE, Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Decode a CHOICE
|
||||
@param in The DER encoded input
|
||||
@param inlen [in/out] The size of the input and resulting size of read type
|
||||
@param list The list of items to decode
|
||||
@param outlen The number of items in the list
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int der_decode_choice(const unsigned char *in, unsigned long *inlen,
|
||||
ltc_asn1_list *list, unsigned long outlen)
|
||||
{
|
||||
unsigned long size, x, z;
|
||||
void *data;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(inlen != NULL);
|
||||
LTC_ARGCHK(list != NULL);
|
||||
|
||||
/* get blk size */
|
||||
if (*inlen < 2) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* set all of the "used" flags to zero */
|
||||
for (x = 0; x < outlen; x++) {
|
||||
list[x].used = 0;
|
||||
}
|
||||
|
||||
/* now scan until we have a winner */
|
||||
for (x = 0; x < outlen; x++) {
|
||||
size = list[x].size;
|
||||
data = list[x].data;
|
||||
|
||||
switch (list[x].type) {
|
||||
case LTC_ASN1_INTEGER:
|
||||
if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
|
||||
if (der_length_integer(data, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_SHORT_INTEGER:
|
||||
if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
|
||||
if (der_length_short_integer(size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_BIT_STRING:
|
||||
if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_bit_string(size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_OCTET_STRING:
|
||||
if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_octet_string(size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_NULL:
|
||||
if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
|
||||
*inlen = 2;
|
||||
list[x].used = 1;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_OBJECT_IDENTIFIER:
|
||||
if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_IA5_STRING:
|
||||
if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LTC_ASN1_PRINTABLE_STRING:
|
||||
if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_UTF8_STRING:
|
||||
if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
|
||||
if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
list[x].size = size;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_UTCTIME:
|
||||
z = *inlen;
|
||||
if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_SET:
|
||||
case LTC_ASN1_SETOF:
|
||||
case LTC_ASN1_SEQUENCE:
|
||||
if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
|
||||
if (der_length_sequence(data, size, &z) == CRYPT_OK) {
|
||||
list[x].used = 1;
|
||||
*inlen = z;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
|
||||
/* $Revision: 1.9 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
96
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
vendored
Normal file
96
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_ia5_string.c
|
||||
ASN.1 DER, encode a IA5 STRING, Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Store a IA5 STRING
|
||||
@param in The DER encoded IA5 STRING
|
||||
@param inlen The size of the DER IA5 STRING
|
||||
@param out [out] The array of octets stored (one per char)
|
||||
@param outlen [in/out] The number of octets stored
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
unsigned long x, y, len;
|
||||
int t;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* must have header at least */
|
||||
if (inlen < 2) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* check for 0x16 */
|
||||
if ((in[0] & 0x1F) != 0x16) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
x = 1;
|
||||
|
||||
/* decode the length */
|
||||
if (in[x] & 0x80) {
|
||||
/* valid # of bytes in length are 1,2,3 */
|
||||
y = in[x] & 0x7F;
|
||||
if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* read the length in */
|
||||
len = 0;
|
||||
++x;
|
||||
while (y--) {
|
||||
len = (len << 8) | in[x++];
|
||||
}
|
||||
} else {
|
||||
len = in[x++] & 0x7F;
|
||||
}
|
||||
|
||||
/* is it too long? */
|
||||
if (len > *outlen) {
|
||||
*outlen = len;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (len + x > inlen) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* read the data */
|
||||
for (y = 0; y < len; y++) {
|
||||
t = der_ia5_value_decode(in[x++]);
|
||||
if (t == -1) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
out[y] = t;
|
||||
}
|
||||
|
||||
*outlen = y;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */
|
||||
/* $Revision: 1.4 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
110
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_integer.c
vendored
Normal file
110
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_integer.c
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_integer.c
|
||||
ASN.1 DER, decode an integer, Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Read a mp_int integer
|
||||
@param in The DER encoded data
|
||||
@param inlen Size of DER encoded data
|
||||
@param num The first mp_int to decode
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
|
||||
{
|
||||
unsigned long x, y, z;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(num != NULL);
|
||||
LTC_ARGCHK(in != NULL);
|
||||
|
||||
/* min DER INTEGER is 0x02 01 00 == 0 */
|
||||
if (inlen < (1 + 1 + 1)) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* ok expect 0x02 when we AND with 0001 1111 [1F] */
|
||||
x = 0;
|
||||
if ((in[x++] & 0x1F) != 0x02) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* now decode the len stuff */
|
||||
z = in[x++];
|
||||
|
||||
if ((z & 0x80) == 0x00) {
|
||||
/* short form */
|
||||
|
||||
/* will it overflow? */
|
||||
if (x + z > inlen) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* no so read it */
|
||||
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
/* long form */
|
||||
z &= 0x7F;
|
||||
|
||||
/* will number of length bytes overflow? (or > 4) */
|
||||
if (((x + z) > inlen) || (z > 4) || (z == 0)) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* now read it in */
|
||||
y = 0;
|
||||
while (z--) {
|
||||
y = ((unsigned long)(in[x++])) | (y << 8);
|
||||
}
|
||||
|
||||
/* now will reading y bytes overrun? */
|
||||
if ((x + y) > inlen) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* no so read it */
|
||||
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if it's negative */
|
||||
if (in[x] & 0x80) {
|
||||
void *tmp;
|
||||
if (mp_init(&tmp) != CRYPT_OK) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
|
||||
mp_clear(tmp);
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
mp_clear(tmp);
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
99
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
vendored
Normal file
99
vendor/stormlib-9/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_decode_object_identifier.c
|
||||
ASN.1 DER, Decode Object Identifier, Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/**
|
||||
Decode OID data and store the array of integers in words
|
||||
@param in The OID DER encoded data
|
||||
@param inlen The length of the OID data
|
||||
@param words [out] The destination of the OID words
|
||||
@param outlen [in/out] The number of OID words
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
|
||||
unsigned long *words, unsigned long *outlen)
|
||||
{
|
||||
unsigned long x, y, t, len;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(words != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* header is at least 3 bytes */
|
||||
if (inlen < 3) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* must be room for at least two words */
|
||||
if (*outlen < 2) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* decode the packet header */
|
||||
x = 0;
|
||||
if ((in[x++] & 0x1F) != 0x06) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* get the length */
|
||||
if (in[x] < 128) {
|
||||
len = in[x++];
|
||||
} else {
|
||||
if (in[x] < 0x81 || in[x] > 0x82) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
y = in[x++] & 0x7F;
|
||||
len = 0;
|
||||
while (y--) {
|
||||
len = (len << 8) | (unsigned long)in[x++];
|
||||
}
|
||||
}
|
||||
|
||||
if (len < 1 || (len + x) > inlen) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* decode words */
|
||||
y = 0;
|
||||
t = 0;
|
||||
while (len--) {
|
||||
t = (t << 7) | (in[x] & 0x7F);
|
||||
if (!(in[x++] & 0x80)) {
|
||||
/* store t */
|
||||
if (y >= *outlen) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
if (y == 0) {
|
||||
words[0] = t / 40;
|
||||
words[1] = t % 40;
|
||||
y = 2;
|
||||
} else {
|
||||
words[y++] = t;
|
||||
}
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen = y;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:24 $ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user