// aplpacket.cpp: implementation of the CaplPacket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "aplPacket.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// Порог размера буфера, данных для ЭЦП, начиная с которого будет использоваться файл
#define APL_MAX_MEM_SIGN_BUFFER 128*1024*1024

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
long crc32tab[256] = {            /* CRC polynomial 0xedb88320 */
	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
		0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
		0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
		0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
		0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
		0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
		0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
		0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
		0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
		0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
		0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
		0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
		0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
		0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
		0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
		0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
		0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
		0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
		0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
		0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
		0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
		0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
		0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
		0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
		0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
		0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
		0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
		0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
		0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
		0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
		0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
		0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
		0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
		0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
		0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
		0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
		0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
		0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
		0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
		0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
		0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
		0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
		0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
		0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
		0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
		0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
		0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
		0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
		0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
		0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
		0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
		0x2d02ef8dL
};

inline UINT32 UpdateCRC32(char c, UINT32 crc){return (crc32tab[((UINT32)(crc) ^ (c)) & 0xff] ^ (((crc) >> 8) &0x00FFFFFFl));};

UINT32 GetCRC32(char *data, UINT32 size)
{
	if(data==0) return -1;
	UINT32 i, crc32=-1;
	for(i=0;i<size;i++)
		crc32=UpdateCRC32(data[i], crc32);
	crc32=~crc32;
	return crc32;
}


// Вычисляет CRC32 файла начиная с текущей позиции до конца файла но не более iMaxByte байт
UINT32 GetFileCRC32(CFile &file, UINT64 iMaxByte) 
{
	UINT32 iDataBufSize=aplGetOptimalBufSize();
	ULONGLONG  flen=file.GetLength();
	if(flen<iDataBufSize) iDataBufSize=(UINT32)flen;

	char *pDataBuf=new char[iDataBufSize];

	UINT32 i, crc32=-1;
	UINT64 nBytes=0;

	long wdlg=0;
	if(flen>16*1024*1024) wdlg=aplStartWaitDlg( APL_T("Вычисление контрольной суммы ..."));

	CString text;

	while(true)
	{
		UINT32 iReadSize=file.Read(pDataBuf,iDataBufSize);
		if(iReadSize<=0) break;
		for(i=0;i<iReadSize;i++)
		{
			crc32=UpdateCRC32(pDataBuf[i], crc32);
			nBytes++;
			if(nBytes>=iMaxByte) {iReadSize=iDataBufSize+1; break;} // Посчитали достаточно
		}
		if(iReadSize<iDataBufSize) break; // Конец файла

		if(0!=wdlg)
		{
			int percent=(int)((100*nBytes)/iMaxByte);
			text.Format( APL_T("Вычисление контрольной суммы ... (%i%%)"), percent);
			aplSetTextWaitDlg(wdlg,text);
		}
	}
	delete pDataBuf;

	if(0!=wdlg) aplEndWaitDlg(wdlg);
	
	crc32=~crc32;
	return crc32;
}

//////////////////////////////////////////////////////////////////////////
CaplPacket::CaplPacket()
{
	m_pRootDataSet = NULL;
	Clear();
}

CaplPacket::~CaplPacket()
{
	Clear();
}

UINT CaplPacket::Load(LPCTSTR lpszPathName)
{
	Clear();
	CString sId;
	try
	{
		CBinaryFile file;
		char head[32];
		CStringA buf;
		CStringA sEtalonHeader = APL_WIN_ETD_HEADER;
		UINT32 fcrc32, crc32;
		UINT32 i,k;
		CSignSert	*pSert;

		if(!file.Open(lpszPathName, CFile::modeRead|CFile::typeBinary)) return false;
		
		file.Read((char *)head, sEtalonHeader.GetLength());
		head[sEtalonHeader.GetLength()]=_T('\0');
		
#ifdef _UNICODE
		if (0==strcmp(head, APL_WIN_ETD_HEADER_U))
		{
			m_global_ansi_string = false;
			file.SetANSI(false);
		}
		else if(0==strcmp(head, APL_WIN_ETD_HEADER))
		{
			m_global_ansi_string = true;
			file.SetANSI(true);
		}
		else
		{
			buf = head;
			if(buf[0]!=_T('<')) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
			if(buf.Mid(1, strlen(APL_WIN_ETD))!=APL_WIN_ETD
				&& buf.Mid(1, strlen(APL_WIN_ETD_U))!=APL_WIN_ETD_U) 
			{
				throw(APL_UNKNOWN_FILE_FORMAT);
			}
			if(buf[buf.GetLength()-1]!=_T('>')) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
			throw(APL_INCORRECT_FILE_VERSION);
		}
#else
		if(0!=memcmp(head, sEtalonHeader, sEtalonHeader.GetLength()))
		{
			if (0==strcmp(head, APL_WIN_ETD_HEADER_U))
			{
				throw(APL_INCOMPATIBLE_FILE_FORMAT);	// нельзя открывать Unicode-файл gjl ANSI-версией
			}
			buf = head;
			if(buf[0]!=_T('<')) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
			if(buf.Mid(1, strlen(APL_WIN_ETD))!=APL_WIN_ETD) throw(APL_UNKNOWN_FILE_FORMAT);
			if(buf[buf.GetLength()-1]!=_T('>')) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
			throw(APL_INCORRECT_FILE_VERSION);
		}
#endif

		//Содержимое пакета
		bool bFolder(false);
#ifdef _UNICODE
		if (m_global_ansi_string)
		{
			bFolder = (file.Read()=='D');
		}
		else
		{
			wchar_t c;
			file.Read(c);
			bFolder = (c==L'D');
		}
#else
		bFolder = (file.Read()=='D');
#endif

		if(bFolder)
			m_pRootDataSet = new CFolderDataSet(this, NULL, m_global_ansi_string);
		else
			m_pRootDataSet = new CFileDataSet(this, NULL, m_global_ansi_string);
		m_pRootDataSet->Load(file);

		m_pRootDataSet->GetParamValueBN(APL_T("Идентификатор"), sId);
		m_pRootDataSet->GetParamValueBN(APL_T("Описание"), m_sDescr);
		m_pRootDataSet->GetParamValueBN(APL_T("Поставщик"), m_sProviderCode);
		m_sId = sId;
		
		// чтение сертификатов
		if(!file.Read(k)) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
		for(i=0; i<k; i++)
		{
			pSert = new CSignSert(this);
			pSert->Load(file);
		}
		
		// чтение подписей
		if(!file.Read(k)) throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
		for(i=0; i<k; i++)
		{
			CDataSetSign *pDSSign = new CDataSetSign(this);
			pDSSign->Load(file);
		}
		
		DWORD dw = (DWORD)file.GetPosition();
		file.Read(fcrc32);
		file.Close();
		
		file.Open(lpszPathName, CFile::modeRead|CFile::typeBinary);
		UINT64 size = file.GetLength()-strlen(APL_WIN_ETD_HEADER)-sizeof(unsigned long);
		if(size>0)
		{
			
			file.Seek(strlen(APL_WIN_ETD_HEADER), CFile::begin);
			crc32=GetFileCRC32(file,size);
			file.Close();
			if(crc32!=fcrc32) throw(APL_CRC32_ERROR);
		}
		else
			throw(APL_LOAD_PACKET_FROM_FILE_ERROR);
		
	}
	catch(int code)
	{
		switch(code)
		{
		case APL_INCORRECT_FILE_VERSION:
			Clear();
			m_sId = sId;
			m_sLoadState = APL_T("Не поддерживаемая версия файла!");
			break;
		case APL_CRC32_ERROR:
			Clear();
			m_sId = sId;
			m_sLoadState = APL_T("Файл поврежден (не совпадают контрольные суммы)!");
			break;
		case APL_INCOMPATIBLE_FILE_FORMAT:
			Clear();
			m_sId = sId;
			m_sLoadState = APL_T("Файл содержит Unicode строки и не может быть прочитан. Используйте версию для unicode.");
			break;
		default:
			Clear();
			m_sId = sId;
			m_sLoadState = APL_T("Некорректный файл (ошибка чтения данных)!");
			break;
		}
		return (UINT)code;
	}
	catch(...)
	{
		Clear();
		m_sId = sId;
		m_sLoadState = APL_T("Некорректный файл (ошибка чтения данных)!");
		return APL_UNKNOWN_ERROR;
	}

	m_sLoadState = APL_T("Корректный");

	return 0;
}

bool CaplPacket::Save(LPCTSTR lpszPathName)
{
	CBinaryFile file(m_global_ansi_string);
	CString buf;
	UINT32 i;
	UINT32 crc32;
	CStringA head;
	
	if(!file.Open(lpszPathName, CFile::modeReadWrite|CFile::modeCreate|CFile::modeRead)) return false;
#ifdef _UNICODE
	if (m_global_ansi_string)
	{
		head = APL_WIN_ETD_HEADER;
	}
	else
	{
		head = APL_WIN_ETD_HEADER_U;
	}
#else
	head = APL_WIN_ETD_HEADER;
#endif
	file.Write(head, head.GetLength());

	m_pRootDataSet->Save(file);
	
	//запись сертификатов
	file.Write((UINT32)m_Sertificates.GetSize());
	for(i=0; i<(UINT32)m_Sertificates.GetSize(); i++)
		m_Sertificates[i]->Save(file);
	
	// запись подписей
	file.Write((UINT32)m_DataSetSigns.GetSize());
	for(i=0; i<(UINT32)m_DataSetSigns.GetSize(); i++)
		m_DataSetSigns[i]->Save(file);

	UINT64 size = file.GetPosition()-strlen(APL_WIN_ETD_HEADER);
	file.Seek(strlen(APL_WIN_ETD_HEADER), CFile::begin);
	crc32 = GetFileCRC32(file,size);
	file.SeekToEnd();
	file.Write(crc32);
	file.Flush();
	file.Close();

	return true;
}

void CaplPacket::Clear()
{
	if(m_pRootDataSet)
		delete m_pRootDataSet;
	m_pRootDataSet = NULL;
	m_sLoadState.Empty();
	m_sDescr.Empty();
	m_sId.Empty();
	m_sProviderCode.Empty();

	while(m_DataSetSigns.GetSize()>0)
		delete m_DataSetSigns[0];
	while(m_Sertificates.GetSize()>0)
		delete m_Sertificates[0];

	m_global_ansi_string = true;
}

int CaplPacket::CheckSigns(bool bShowMessages)
{
	if(m_pRootDataSet)
	{
		int res = m_pRootDataSet->CheckSigns(false);
		if(res==APL_CRYPT_NO_ERROR)
		{
			if(bShowMessages)
				AfxMessageBox(APL_T("Подписи верны!"), MB_OK|MB_ICONINFORMATION);
			m_sLoadState = APL_T("Проверен");
		}
		else if(res!=APL_CRYPT_NO_ERROR)
		{
			if(bShowMessages)
				AfxMessageBox(APL_T("Подписи не верны!"), MB_OK|MB_ICONINFORMATION);
			m_sLoadState = APL_T("Некорректный");
		}
		return res;
	}

	return APL_CRYPT_UNKNOWN_ERROR;
}

bool CaplPacket::SaveAsFiles(LPCTSTR lpszPathName, CStringArray *sFiles)
{
	CString sPath = lpszPathName;
	int i;
	CDataSet *pDS;

	for(i=0; i<m_DataSets.GetSize(); i++)
	{
		pDS = m_DataSets[i];
		if(pDS->IsFolder()) continue;

		pDS->SaveFiles(sPath);
		if(sFiles) sFiles->Add(sPath + pDS->m_sName);
	}

	return true;
}

void CaplPacket::SetANSI(bool bANSI)
{
	m_global_ansi_string = bANSI;

	for(int i=0; i<m_DataSets.GetSize(); ++i)
	{
		m_DataSets[i]->SetANSI(bANSI);
	}
}

//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************

CaplSignBuf::CaplSignBuf()
{
	m_pBuf=0;
	m_DataAllSize=0;
	m_BufSize=0;
	m_DataInBufSize=0;
	m_bFileMode=false;
}

//**************************************************************************************

CaplSignBuf::~CaplSignBuf()
{
	Clear();
}

//**************************************************************************************

void CaplSignBuf::Clear()
{
	if(0!=m_pBuf) delete m_pBuf;
	m_pBuf=0;
	m_DataAllSize=0;
	m_BufSize=0;
	m_DataInBufSize=0;
	m_bFileMode=false;

	if(m_sDataFile!=_T(""))
	{
		::SetFileAttributes(m_sDataFile,FILE_ATTRIBUTE_NORMAL);
		CaplFile::Remove(m_sDataFile);
		m_sDataFile=_T("");
	}
}

UINT64 CaplSignBuf::GetAllDataSize() // Возвращаетр размер всех данных
{
	return m_DataAllSize;
}
//**************************************************************************************

UINT32 CaplSignBuf::GetDataSize()
{
	if(m_bFileMode) return 0;
	return (UINT32)m_DataAllSize;
}

//**************************************************************************************

BYTE *CaplSignBuf::GetData()
{
	if(m_bFileMode)
	{
		Flush();
		return (BYTE*)(LPCTSTR) m_sDataFile;
	}
	else return m_pBuf;
}

//**************************************************************************************
bool CaplSignBuf::Add(char c)
{
	return Add((BYTE*)&c,sizeof(char));
}
//**************************************************************************************
bool CaplSignBuf::Add(UINT32 i)
{
	return Add((BYTE*)&i,sizeof(UINT32));
}
//**************************************************************************************
bool CaplSignBuf::Add(CString &str,  bool bANSI)
{
	int slen=str.GetLength();
	Add((BYTE*)&slen,sizeof(UINT32));

#ifdef _UNICODE
	if (bANSI)
	{
		// переводим строку в ANSI
		CaplStringAdapter sAdapter(str);
		LPCSTR pBufANSI = (LPCSTR)sAdapter;
		Add((BYTE*)LPCSTR(pBufANSI),slen+1); // вкючая 0
	}
	else
	{
		// пишем Unicode-строку
		Add((BYTE*)LPCWSTR(str),(slen+1) * sizeof(wchar_t));  // вкючая 0
	}
#else
	Add((BYTE*)LPCSTR(str),slen+1);  // вкючая 0
#endif
	return true;
}

//*****************************************************************************

bool CaplSignBuf::AddFile(LPCTSTR sFilePath)
{
	if(0==sFilePath) return false;
	if(_T('\0')==sFilePath[0]) return false;

	CFile InFile;
	if(!InFile.Open(LPCTSTR(sFilePath),CFile::modeRead|CFile::typeBinary)) return false;
	ULONGLONG flen=InFile.GetLength();

	int iDataBufSize=aplGetOptimalBufSize();
	if(flen < iDataBufSize)iDataBufSize=(int)flen;
	BYTE *pDataBuf=new BYTE[iDataBufSize];
	while(true)
	{
		int iReadSize=InFile.Read(pDataBuf,iDataBufSize);
		if(iReadSize<=0) break;
		Add(pDataBuf, iReadSize);
		if(iReadSize<iDataBufSize) break; // Конец файла
	}
	delete pDataBuf; pDataBuf=0;
	InFile.Close();
	return true;
}

//*************************************************************

bool CaplSignBuf::Add(BYTE *addData, UINT32 addDataSize)
{
	if( m_DataInBufSize + addDataSize > m_BufSize)
	{
		UINT32 newBufSize = m_BufSize*2;
		if(0==newBufSize) newBufSize=4*1024*1024;
		if( (m_DataInBufSize + addDataSize) > newBufSize) newBufSize= m_DataInBufSize + addDataSize + 4096; // (UINT32)- Больше 4 Гб всё равно не подписываем
		
		if(newBufSize < APL_MAX_MEM_SIGN_BUFFER)
		{
			BYTE *newbuf=new BYTE[newBufSize];
			if(0==newbuf) return false;

			memcpy(newbuf,m_pBuf,m_DataInBufSize);
			delete m_pBuf;
			m_pBuf=newbuf;
			m_BufSize=newBufSize;
		}
		else
		{
			// Переходим в режим файла
			Flush();
			if(addDataSize>=m_BufSize) // Данные всё равно не поместятся в буфер
			{
				SaveDataToFile(addData,addDataSize);
				m_DataAllSize+=addDataSize;
				return true;
			}
		}
	}

	// Короткие типы данных делаем без memcpy
	if(addDataSize==sizeof(char)) *(char*)(m_pBuf + m_DataInBufSize) = *(char*)addData;
	else if(addDataSize==sizeof(wchar_t)) *(wchar_t*)(m_pBuf + m_DataInBufSize) = *(wchar_t*)addData;
	else if(addDataSize==sizeof(UINT32)) *(UINT32*)(m_pBuf + m_DataInBufSize) = *(UINT32*)addData;
	else
	{
		memcpy(m_pBuf + m_DataInBufSize, addData, addDataSize);
	}
	m_DataAllSize+=addDataSize;
	m_DataInBufSize+=addDataSize;
	return true;
}

//*************************************************************
bool CaplSignBuf::Flush()
{
	if(0==m_DataInBufSize)return true;
	if(!SaveDataToFile(m_pBuf,m_DataInBufSize)) return false;
	m_DataInBufSize=0;
	return true;
}

//*************************************************************

bool CaplSignBuf::SaveDataToFile(BYTE *addData, UINT32 addDataSize)
{
	if(0==addDataSize) return true;
	if(0==addData) return false;

	CFile file;
	if(m_sDataFile==_T(""))
	{
		CString tmp_file;
		aplGetTempFileName(_T("winetd-sign"),_T("tmp"),tmp_file);
		if(!file.Open(LPCTSTR(tmp_file),CFile::modeCreate|CFile::modeWrite|CFile::typeBinary)) return false;
		m_sDataFile=tmp_file;
		m_bFileMode=true;
	}
	else
	{
		if(!file.Open(LPCTSTR(m_sDataFile),CFile::modeWrite|CFile::typeBinary)) return false;
		file.SeekToEnd();
	}

	if(addDataSize>0) file.Write(addData,addDataSize);

	file.Flush();
	file.Close();

	return true;
}