Author: 1. Date 2016-09-27 19:40:31, views: 637, Raw

Увеличить
#pragma once
#include <WTypes.h>
 
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define __INTEL_BYTE_ORDER__ 1
#endif
 
class FArchive
{
public:
	// FArchive interface.
	virtual ~FArchive()
	{
	}
 
	virtual void Serialize(void* V, INT Length)
	{
	}
 
	virtual void SerializeBits(void* V, INT LengthBits)
	{
		Serialize(V, (LengthBits + 7) / 8);
		if (IsLoading())
			((BYTE*)V)[LengthBits / 8] &= ((1 << (LengthBits & 7)) - 1);
	}
 
	virtual void SerializeInt(DWORD& Value, DWORD Max)
	{
		*this << *(DWORD*)Value;
	}
 
	virtual void Preload(void* Object)
	{
	}
 
	virtual void CountBytes(SIZE_T InNum, SIZE_T InMax)
	{
	}
 
	virtual FArchive& operator<<(class FName& N)
	{
		return *this;
	}
 
	virtual FArchive& operator<<(class UObject*& Res)
	{
		return *this;
	}
 
	virtual INT MapName(FName* Name)
	{
		return 0;
	}
 
	virtual INT MapObject(UObject* Object)
	{
		return 0;
	}
 
	virtual INT Tell()
	{
		return -1;
	}
 
	virtual INT TotalSize()
	{
		return -1;
	}
 
	virtual BOOL AtEnd()
	{
		INT Pos = Tell();
		return Pos != -1 && Pos >= TotalSize();
	}
 
	virtual BOOL AtStopper()
	{
		BOOL res = FALSE;
 
		INT Size = TotalSize();
		if (Size != -1)
		{
			if (ArStopper != -1 && Size >= ArStopper)
				res = TRUE;
		}
 
		return res;
	}
 
	virtual void SetStopper(INT Stopper)
	{
		ArStopper = Stopper;
	}
 
	virtual void Seek(INT InPos)
	{
	}
 
	virtual void AttachLazyLoader(void* LazyLoader)
	{
	}
 
	virtual void DetachLazyLoader(void* LazyLoader)
	{
	}
 
	virtual void AttachRoughLoader(void* RoughLoader)
	{
	}
 
	virtual void DetachRoughLoader(void* RoughLoader)
	{
	}
 
	virtual void Precache(INT HintCount)
	{
	}
 
	virtual void Flush()
	{
	}
 
	virtual BOOL Close()
	{
		return !ArIsError;
	}
 
	virtual BOOL GetError()
	{
		return ArIsError;
	}
 
	virtual INT GetCurrentEncryptVersion()
	{
		return 0;
	}
 
	// Hardcoded datatype routines that may not be overridden.
	FArchive& ByteOrderSerialize(void* V, INT Length)
	{
#if __INTEL_BYTE_ORDER__
		Serialize(V, Length);
#else
		if( ArIsPersistent )
		{
		// Transferring between memory and file, so flip the byte order.
			for( INT i=Length-1; i>=0; i-- )
				Serialize( (BYTE*)V + i, 1 );
		}
		else
		{
		// Transferring around within memory, so keep the byte order.
			Serialize( V, Length );
		}
#endif
		return *this;
	}
 
	// Constructor.
	FArchive()
		: ArVer(/*PACKAGE_FILE_VERSION*/0x7B)
		  , ArNetVer(/*ENGINE_NEGOTIATION_VERSION*/0x7D0)
		  , ArLicenseeVer(/*PACKAGE_FILE_VERSION_LICENSEE*/0x1E)
		  , ArIsLoading(0)
		  , ArIsSaving(0)
		  , ArIsTrans(0)
		  , ArIsPersistent(0)
		  , ArIsError(0)
		  , ArForEdit(0)
		  , ArForClient(0)
		  , ArForServer(0)
		  , ArUnk1(0)
		  , ArStopper(-1)
	{
	}
 
	// Status accessors.
	INT Ver()
	{
		return ArVer;
	}
 
	INT NetVer()
	{
		return ArNetVer & 0x7fffffff;
	}
 
	INT LicenseeVer()
	{
		return ArLicenseeVer;
	}
 
	BOOL IsLoading()
	{
		return ArIsLoading;
	}
 
	BOOL IsSaving()
	{
		return ArIsSaving;
	}
 
	BOOL IsTrans()
	{
		return ArIsTrans;
	}
 
	BOOL IsNet()
	{
		return (ArNetVer & 0x80000000) != 0;
	}
 
	BOOL IsPersistent()
	{
		return ArIsPersistent;
	}
 
	BOOL IsError()
	{
		return ArIsError;
	}
 
	BOOL ForEdit()
	{
		return ArForEdit;
	}
 
	BOOL ForClient()
	{
		return ArForClient;
	}
 
	BOOL ForServer()
	{
		return ArForServer;
	}
 
	// Friend archivers.
	friend FArchive& operator<<(FArchive& Ar, PCHAR& C)
	{
		Ar.Serialize(&C, 1);
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, BYTE& B)
	{
		Ar.Serialize(&B, 1);
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, CHAR& B)
	{
		Ar.Serialize(&B, 1);
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, WORD& W)
	{
		Ar.ByteOrderSerialize(&W, sizeof(W));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, SHORT& S)
	{
		Ar.ByteOrderSerialize(&S, sizeof(S));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, DWORD& D)
	{
		Ar.ByteOrderSerialize(&D, sizeof(D));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, INT& I)
	{
		Ar.ByteOrderSerialize(&I, sizeof(I));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, FLOAT& F)
	{
		Ar.ByteOrderSerialize(&F, sizeof(F));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, DWORD64& Q)
	{
		Ar.ByteOrderSerialize(&Q, sizeof(Q));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, long long& S)
	{
		Ar.ByteOrderSerialize(&S, sizeof(S));
		return Ar;
	}
 
	friend FArchive& operator<<(FArchive& Ar, /*FTime*/INT& F);
 
public:
	// Status variables.
	INT ArVer;
	INT ArNetVer;
	INT ArLicenseeVer;
	BOOL ArIsLoading;
	BOOL ArIsSaving;
	BOOL ArIsTrans;
	BOOL ArIsPersistent;
	BOOL ArForEdit;
	BOOL ArForClient;
	BOOL ArForServer;
	BOOL ArIsError;
	BOOL ArUnk1;
	INT ArStopper;
};
 
class FArchiveFileReader : public FArchive
{
public:
	FArchiveFileReader(HANDLE InFile, void* InError, INT InSize)
		: File(InFile)
		  , Error(InError)
		  , Size(InSize)
		  , Pos(0)
		  , BufferBase(0)
		  , BufferCount(0)
		  , SleepFactor(0.0f)
	{
		SetFilePointer(File, 0, 0, FILE_BEGIN);
		ArIsLoading = ArIsPersistent = 1;
	}
 
	~FArchiveFileReader()
	{
		if (File)
		{
			FArchiveFileReader::Close();
		}
	}
 
	void Precache(INT HintCount) override
	{
		BufferBase = Pos;
		BufferCount = min( min( HintCount, (INT)(ARRAYSIZE(Buffer) - (Pos & (ARRAYSIZE(Buffer)-1))) ), Size-Pos );
 
		if (!ReadFile(File, Buffer, BufferCount) && BufferCount != 0)
		{
			ArIsError = 1;
			//Error->Logf( TEXT("fread failed: BufferCount=%i"), BufferCount );
			return;
		}
	}
 
	void Seek(INT InPos) override
	{
		//assert(InPos >= 0);
		//assert(InPos <= Size);
 
		if (SetFilePointer(File, InPos, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
		{
			ArIsError = 1;
			//Error->Logf( TEXT("Seek failed: %i/%i: %i"), InPos, Size, Pos );
		}
 
		Pos = InPos;
		BufferBase = Pos;
		BufferCount = 0;
	}
 
	INT Tell() override
	{
		return Pos;
	}
 
	INT TotalSize() override
	{
		return Size;
	}
 
	BOOL Close() override
	{
		if (File)
			CloseHandle(File);
		File = NULL;
 
		return !ArIsError;
	}
 
	void Serialize(void* V, INT Length) override
	{
		while (Length > 0)
		{
			INT Copy = min( Length, BufferBase+BufferCount-Pos );
			if (Copy == 0)
			{
				if (Length >= ARRAYSIZE(Buffer))
				{
					if (!ReadFile(File, V, Length))
					{
						ArIsError = 1;
						//Error->Logf( TEXT("fread failed: Length=%i"), Length );
					}
 
					Pos += Length;
					BufferBase += Length;
					return;
				}
 
				Precache(MAXINT);
 
				Copy = min( Length, BufferBase + BufferCount - Pos );
				if (Copy <= 0)
				{
					ArIsError = 1;
					//Error->Logf( TEXT("ReadFile beyond EOF %i+%i/%i"), Pos, Length, Size );
				}
 
				if (ArIsError)
					return;
			}
 
			::memcpy(V, Buffer + Pos - BufferBase, Copy);
			Pos += Copy;
			Length -= Copy;
			V = (BYTE*)V + Copy;
		}
	}
 
	BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead)
	{
		DWORD dwRead = 0;
		BOOL readOk = ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, &dwRead, 0) && nNumberOfBytesToRead == dwRead;
 
		return readOk;
	}
 
public:
	HANDLE File;
	void* Error;
	INT Size;
	INT Pos;
	INT BufferBase;
	INT BufferCount;
	float SleepFactor;
	BYTE Buffer[1024];
};
 
extern wchar_t GLineage2Ver[12];
 
DWORD Get121Key(const wchar_t* FileName);
 
class FL2FileDecryptArchive : public FArchive
{
public:
	FL2FileDecryptArchive(HANDLE InFile, void* InError, INT InSize, const wchar_t* FileName) : ArchiveFileReader(nullptr), CryptVer(0), HeaderSize(0), CryptKey(0xAC)
	{
		FArchiveFileReader* reader = new FArchiveFileReader(InFile, InError, GetFileSize(InFile, 0));
 
		ArchiveFileReader = reader;
 
		if (InSize <= 0x18)
		{
			ArchiveFileReader->Seek(0);
		}
		else
		{
			for (int i = 0; i < 11; ++i)
			{
				wchar_t c;
				ArchiveFileReader->Serialize(&c, sizeof(c));
				if (c != GLineage2Ver[i])
				{
					ArchiveFileReader->Seek(0);
					return;
				}
			}
 
			wchar_t buf_ver[3];
			ArchiveFileReader->Serialize(&buf_ver[0], sizeof(wchar_t));
			ArchiveFileReader->Serialize(&buf_ver[1], sizeof(wchar_t));
			ArchiveFileReader->Serialize(&buf_ver[2], sizeof(wchar_t));
 
			long ver = wcstol(buf_ver, 0, 10);
 
			CryptVer = ver;
			HeaderSize = 28;
 
			if (CryptVer == 111)
			{
				CryptKey = 0xAC;
			}
			else if (CryptVer == 121)
			{
				CryptKey = static_cast<BYTE>(Get121Key(FileName));
			}
			else
			{
				CryptKey = 0;
			}
		}
	}
 
	~FL2FileDecryptArchive()
	{
		if(ArchiveFileReader)
		{
			delete ArchiveFileReader;
			ArchiveFileReader = 0;
		}
	}
 
	void Serialize(void* V, INT Length) override
	{
		int ver = CryptVer;
		if (ver > 212)
		{
			if (ver != 311 && ver - 411 > 2)
				return;
 
			ArchiveFileReader->Serialize(V, Length);
			return;
		}
 
		if (ver >= 211 || !ver)
		{
			ArchiveFileReader->Serialize(V, Length);
			return;
		}
 
		if (ver == 111 || ver == 121)
		{
			ArchiveFileReader->Serialize(V, Length);
 
			for (int i = 0; i < Length; ++i)
				*((BYTE*)V + i) ^= this->CryptKey;
		}
	}
 
	INT Tell() override
	{
		int ver = CryptVer;
 
		if (ver > 212)
		{
			if (ver != 311 && ver - 411 > 2)
				return -1;
 
			return ArchiveFileReader->Tell() - this->HeaderSize;
		}
 
		if (ver >= 211)
			return ArchiveFileReader->Tell() - this->HeaderSize;
 
		if (!ver)
			return ArchiveFileReader->Tell();
 
		if (ver == 111 || ver == 121)
			return ArchiveFileReader->Tell() - this->HeaderSize;
 
		return -1;
	}
 
	INT TotalSize() override
	{
		int ver = CryptVer;
 
		if (ver > 212)
		{
			if (ver != 311 && ver - 411 > 2)
				return -1;
 
			return ArchiveFileReader->TotalSize() - this->HeaderSize;
		}
 
		if (ver >= 211)
			return ArchiveFileReader->TotalSize() - this->HeaderSize;
 
		if (!ver)
			return ArchiveFileReader->TotalSize();
 
		if (ver == 111 || ver == 121)
			return ArchiveFileReader->TotalSize() - this->HeaderSize;
 
		return -1;
	}
 
	void Seek(INT InPos) override
	{
		int ver = this->CryptVer;
		if (ver > 212)
		{
			if (ver != 311 && ver - 411 > 2)
				return;
 
			ArchiveFileReader->Seek(InPos + this->HeaderSize);
			return;
		}
 
		if (ver >= 211)
		{
			ArchiveFileReader->Seek(InPos + this->HeaderSize);
			return;
		}
 
		if (!ver)
		{
			ArchiveFileReader->Seek(InPos);
			return;
		}
 
		if (ver == 111 || ver == 121)
			ArchiveFileReader->Seek(InPos + this->HeaderSize);
	}
 
	void Precache(INT HintCount) override
	{
		int ver = this->CryptVer;
		if (ver > 212)
		{
			if (ver != 311 && (unsigned int)(ver - 411) > 2)
				return;
 
			ArchiveFileReader->Precache(HintCount);
			return;
		}
 
		if (ver >= 211 || !ver)
		{
			ArchiveFileReader->Precache(HintCount);
		}
		else if (ver == 111 || ver == 121)
		{
			ArchiveFileReader->Precache(HintCount);
		}
	}
 
	BOOL Close() override
	{
		int ver = this->CryptVer;
		if (ver > 212)
		{
			if (ver != 311 && (unsigned int)(ver - 411) > 2)
				return ArForServer == 0;
 
			return ArchiveFileReader->Close();
		}
 
		if (ver >= 211 || !ver)
		{
			return ArchiveFileReader->Close();
		}
 
		if (ver == 111 || ver == 121)
		{
			return ArchiveFileReader->Close();
		}
 
		return ArForServer == 0;
	}
 
	INT GetCurrentEncryptVersion() override
	{
		return CryptVer;
	}
 
public:
	FArchiveFileReader* ArchiveFileReader;
	int CryptVer;
	int HeaderSize;
	BYTE CryptKey;
};