Serializable CListCtrl with check sum verify

More questions on Discussion board are based on store/load a list control to file. One way to serialize the list control is to save information about the header of list control, and then serialize all items from list control. The idea is to open a file in CFile::modeCreate or CFile::modeRead depending on kind of operation, store or load the list control. Then we will create a archive object from this file to easily store/load the objects. For more security this method has implemented a check sum of file.

Storing information in file.

First we will save a signature, as sample I chose this to be 'ListCtrl - ObjectStore', for a short check of file type. Then we will store a double word where at the end of the storing operation we will put the calculated check sum. After that, each column in stored, and finished with a -1 value to limit the definitions of columns in file.

Loading information from file.

Read signature. If this is what I stored, then I get the check sum from file, to verify with check sum of file. If all these are right,the loading continues as with the storing procedure.

The implementation contain a class CCheckArchive, and function Serialize. The CCheckArchive class has some virtual functions overridable ( like operator <<, used in Serialize functions) to complete the check sum.

For more detail, I invite the user to see the code. For store/load list control the user can call the function ::Serialize, with the folowing arguments. First is the destinatin list control, the second is the file name, and the last argument is the required operation; TRUE for storing, FALSE for loading. I think that the function Serialize and CCheckArchive, can be easly extended. Any kind of help, or information I will receive/send with pleasure.

Sincerely, Mihai Filimon

class CCheckArchive : public CArchive
{
	DWORD m_wCheckSum;
protected:

	// Function name : Sum
	// Description   : Add every byte from wData
	// Return type   : static DWORD
	// Argument      : DWORD wData
	static DWORD Sum(DWORD wData)
	{
		return HIBYTE(HIWORD(wData)) + LOBYTE(HIWORD(wData)) +
				HIBYTE(LOWORD(wData)) + LOBYTE(LOWORD(wData));
	};

public:

	// Function name : CCheckArchive
	// Description   : Contructor uses in Serialize() function
	// Return type   :
	// Argument      : CFile* pFile
	// Argument      : UINT nMode
	CCheckArchive(CFile* pFile, UINT nMode) : CArchive( pFile, nMode, 4096, NULL )
	{
		m_wCheckSum = 0;
	}

	// Function name : ~CCheckArchive
	// Description   : Destructor
	// Return type   : virtual
	virtual ~CCheckArchive() {};

	// Function name : operator <<
	// Description   : This operator is call in Serialize function. Add
	//				   every byte write in file, in m_wCheckSum
	// Return type   : virtual CArchive&
	// Argument      : DWORD wData
	virtual CArchive& operator << (DWORD wData)
	{
		m_wCheckSum += Sum(wData);
		return ((CArchive&)*this) << wData;
	}

	// Function name : operator <<
	// Description   : This operator is call in Serialize function. Add
	//				   every byte write in file, in m_wCheckSum
	// Return type   : virtual CArchive&
	// Argument      : CString& sData
	virtual CArchive& operator << (CString& sData)
	{
		LPTSTR lpszS = (LPTSTR)(LPCTSTR)sData;

		while (*lpszS)
		m_wCheckSum += BYTE(*lpszS++);
		m_wCheckSum += Sum(sData.GetLength());
		return ((CArchive&)*this) << sData;
	}

	// Function name : GetCheckSum
	// Description   : Return the calculated check sum
	// Return type   : DWORD
	DWORD GetCheckSum()
	{
		return m_wCheckSum;
	};

	// Function name : GetLastPosition
	// Description   : Called for found the position of file in write
	//				   operation
	// Return type   : DWORD
	DWORD GetLastPosition()
	{
		return m_lpBufCur - m_lpBufStart;
	};

	// Function name : Verify
	// Description   : Check if chkSum verify the file, that must be in
	//				   loading
	// Return type   : BOOL
	// Argument      : DWORD chkSum
	BOOL Verify(DWORD chkSum)
	{
		static const max = 2048;
		DWORD w = 0;
		ASSERT (IsLoading());
		TRY
		{
			CFile* pFile = GetFile();
			DWORD bookmark = pFile->GetPosition();
			pFile->SeekToBegin();
			BYTE buffer[max], *pBuffer = NULL;
			int nRead = 0;
			while (nRead = pFile->Read(&buffer, max))
			{
				pBuffer = buffer;
				for (int i = 0; i < nRead; i++, w += *pBuffer++);
			}
			w -= Sum(chkSum);
			pFile->Seek(bookmark, CFile::begin);
		}
		CATCH_ALL(e)
		{
			return FALSE;
		}
		END_CATCH_ALL;
		return w == chkSum;
	}
};

// Function name : Serialize
// Description   : Call this function to store/load a list control
// Return type   : BOOL
// Argument      : CListCtrl* pListCtrl
// Argument      : LPCTSTR lpszFileName
// Argument      : BOOL bStoring = TRUE
BOOL Serialize(CListCtrl* pListCtrl, LPCTSTR lpszFileName, BOOL bStoring = TRUE)
{
	static const TCHAR* lpszSignature = _T("ListCtrl - StoreObject");
	CFile file;
	if (file.Open(lpszFileName, bStoring ? CFile::modeWrite | CFile::modeCreate: CFile::modeRead))
	TRY
	{
		CString s; CCheckArchive ar(&file, bStoring ? CArchive::store :CArchive::load);
		DWORD chkSum = 0;
		if (bStoring)
		{
			ar << CString(lpszSignature);
			DWORD sC = ar.GetLastPosition();
			ar << chkSum;
			LV_COLUMN column; TCHAR buffer[MAX_PATH]; int i = NULL, nColumn = 0;

			column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
			column.pszText = buffer;
			column.cchTextMax = MAX_PATH;
			for (i = 0; pListCtrl->GetColumn(i, &column); i++, nColumn++)
			{
				ar << column.fmt;
				ar << column.cx;
				ar << CString(column.pszText);
			}
			ar << UINT(-1);
			int n = pListCtrl->GetItemCount();
			ar << n;
			for (i = 0; i < n; i++)
			{
				for (int j = 0; j < nColumn; j++)
				ar << pListCtrl->GetItemText(i, j);
				ar << pListCtrl->GetItemData(i);
			}
			ar.Flush();
			ar.GetFile()->Seek(sC,CFile::begin);
			chkSum = ar.GetCheckSum();
			ar.GetFile()->Write(&chkSum, sizeof(chkSum));
		}
		else
		{
			ar >> s;
			if (s.Compare(lpszSignature) == 0)
			{
				ar >> chkSum;
				if (ar.Verify(chkSum))
				{
					CString text;
					text.Format(_T("%i"),chkSum);
					AfxMessageBox(text);
					LV_COLUMN column; TCHAR buffer[MAX_PATH]; int i = NULL, nColumn = 0;
					column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
					column.pszText = buffer;
					column.cchTextMax = MAX_PATH;
					for (; TRUE; nColumn++)
					{
						ar >> column.fmt;
						if (column.fmt < 0) break;
						ar >> column.cx;
						ar >> s;
						column.pszText = (LPTSTR)(LPCTSTR)s;
						pListCtrl->InsertColumn(nColumn, &column);
					}
					int n = NULL;
					ar >> n;
					for (i = 0; i < n; i++)
					{
						int nItem = pListCtrl->InsertItem(i, _T(""));
						for (int j = 0; j < nColumn; j++)
						{
							ar >> s;
							pListCtrl->SetItemText(nItem, j, s);
						}
						DWORD wData;
						ar >> wData;
						pListCtrl->SetItemData(nItem, wData);
					}
				}
			}
		}
		ar.Close();
		file.Close();
	}
	CATCH_ALL(e)
	{
		return FALSE;
	}
	END_CATCH_ALL
	return TRUE;
}

Last updated: 29 July 1998 by Rob Osborne



Comments

  • Try CExtReport

    Posted by Legacy on 08/18/2003 12:00am

    Originally posted by: marcus gesing

    Source and demo:
    http://home.arcor.de/footwear-box/various/coding/ExtLib.zip

    Reply
  • I need help using the mfc serialize funktion width your code

    Posted by Legacy on 05/12/2000 12:00am

    Originally posted by: Andreas H

    I have to tell you this cameas a dream. I m at the moment
    involved in my first project involving serializing data to and from files.
    However as you might have guest im not that good in programming vc++.
    Ive only been doing this for 5 months and im learning not only by books
    but also from taking codes from codeguru.com for use in my applications.
    Unfortunatly i dont quite understand your code posted there.
    Because instead of using a new class i want to used the MFC serialize function.
    I tried to modify it without any bigger succes, since i didnt really know
    where to put the checksum finctions and so on. So i was kind of hoping for
    that you could help me out. I would really appreciate the help.
    In my project I have a listview cointaing data in 2 cols and a unspecified
    number of rows. I also have 2 edit boxes containing 3 strings of text.
    I need al this serialized into the file.
    The name of the variables:
    CListCtrl = m_lstSourceFiles
    Editbox1 = m_strFolder
    Editbox2 = m_strContent
    Editbox3 = m_strName
    Please help me modify the code for my needs and be detailed in your
    explanations so that i can learn it.

    Thank you

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The world of data storage is changing around us as organizations continue to seek ways by which they can leverage cloud-based services. However, simply shifting everything to the public cloud is generally neither desirable nor feasible, so organizations are struggling with finding ways that they can leverage the public cloud and its outcomes where it makes sense and leave everything else on-premises. The Gorilla Guide lays out the key questions and considerations you need to think through in building your …

  • On-demand EventEvent Date: March 21, 2017 With the rise in ransomware attacks, bank heists that reached new levels of sophistication, and extortion plots that were beyond anything we could have imagined, 2016 certainly was an eventful year for cybersecurity. Going into 2017, no business can afford to be uninformed about cybersecurity or unprepared for an attack. Watch this informative webinar, presented by Andrey Pozhogin, Senior B2B Product Marketing Manager at Kaspersky Lab, as he examines predictions for …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date