Serializing CStringList in the registry
I recently encountered a scenario where I needed to store a list of strings in the registry. Typically, that would involve ::RegOpenKeyEx(key) followed by a series of ::RegSetValueEx(ValueName, ValueData). Unfortunately, I didn't have any Value Names for the list of strings to store. In other words, if I have 5 strings to write into the registry, I would need to generate 5 different Value Names to uniquely identify each string. Here's what the registry would look like:
Key: SOFTWARE\Commpany\App\strings Value Name and Value Data: a = "string1" b = "string2" c = "string3" d = "string4" e = "string5"
The downside of this technique is the excessive number of Value Names, and the pseudo-random generation of those names. My original need of storing N strings would be better served by specifying only one Value Name along with a string list.
The technique I implemented consists of serializing a CStringList using MFCs CMemFile, CArchive and the registry's REG_BINARY data type. The registry is not the appropriate place to store massive amounts of data, and anything over 2K should be stored as a separate file outside the registry. Therefore, I placed a hard coded limit of 4096 bytes for the string list.
The code was tested using Microsoft Visual C++ 5.0sp3 under Windows 95.
// skip registry key opening sequence for clarity
const INT nSIZE = 4096;
DWORD dwType;
DWORD dwData = nSIZE;
BYTE* bData = (BYTE*)::calloc(nSIZE, sizeof(TCHAR));
ASSERT(bData);
const LONG retValue = ::RegQueryValueEx(hKey, pszValueName, NULL, &dwType,
bData, &dwData);
if(retValue == ERROR_SUCCESS and REG_BINARY == dwType){
ASSERT(dwData < nSIZE);
try{
// Read
CMemFile file(bData, nSIZE);
CArchive ar(&file, CArchive::load);
ar.m_bForceFlat = FALSE;
ASSERT( ar.IsLoading() );
CStringList myList;
ASSERT( myList.IsSerializable() );
myList.Serialize(ar);
ar.Close();
file.Close();
myList.AddTail("Another string!");
// Write
file.Attach(bData, nSIZE, 16);
CArchive ar2(&file, CArchive::store);
ASSERT(myList.IsSerializable());
myList.Serialize(ar);
ar2.Close();
const DWORD dwLen = file.GetLength();
ASSERT(dwLen < nSIZE);
::RegSetValueEx(hKey, pszValueName, 0, REG_BINARY, file.Detach(), dwLen);
}
catch(CMemoryException* e){
e->ReportError();
e->Delete();
}
catch(CArchiveException* e){
e->ReportError();
e->Delete();
}
catch(CFileException* e){
e->ReportError();
e->Delete();
}
if(bData) free(bData); bData = NULL;
}

Comments
There are no comments yet. Be the first to comment!