Re: Skipping parts of a serialized file
Following the suggestions of others, I added the lpstorage and
COleStreamFile code from the COleDocument loading algorithm, and this
appears to do the trick. I have not stress-tested this yet, but the
following appears to work:
bool Decoder::OpenAndReadPreamble(CString p_csFilename,
COleStreamFile* p_pfr)
{
//The preamble is completely and utterly unimportant. This gets
written
//even if (Name removed for confidentiality) doesn't even save the
file! It's runtime information left over
//from serialization. We just... plain... don't care.
LPSTORAGE lpRootStg = NULL;
//This is based on the COleDocument code for reading.
BOOL bResult = FALSE;
TRY
{
if (lpRootStg == NULL)
{
LPCOLESTR lpsz = T2COLE(p_csFilename);
// use STGM_CONVERT if necessary
SCODE sc;
LPSTORAGE lpStorage = NULL;
if (StgIsStorageFile(lpsz) == S_FALSE)
{
// convert existing storage file
sc = StgCreateDocfile(lpsz, STGM_READWRITE|
STGM_TRANSACTED|/*STGM_SHARE_EXCLUSIVE|*/STGM_CONVERT,
0, &lpStorage);
if (FAILED(sc) || lpStorage == NULL)
sc = StgCreateDocfile(lpsz, STGM_READ|
STGM_TRANSACTED|/*STGM_SHARE_EXCLUSIVE|*/STGM_CONVERT,
0, &lpStorage);
}
else
{
// open new storage file
sc = StgOpenStorage(lpsz, NULL,
STGM_READWRITE|STGM_TRANSACTED/*|STGM_SHARE_EXCLUSIVE*/,
0, 0, &lpStorage);
if (FAILED(sc) || lpStorage == NULL)
sc = StgOpenStorage(lpsz, NULL,
STGM_READ|STGM_TRANSACTED/*|STGM_SHARE_EXCLUSIVE*/,
0, 0, &lpStorage);
}
if (FAILED(sc))
AfxThrowOleException(sc);
ASSERT(lpStorage != NULL);
lpRootStg = lpStorage;
}
ASSERT(lpRootStg != NULL);
// open Contents stream
CFileException fe;
if (!p_pfr->OpenStream(lpRootStg, _T("Contents"),
CFile::modeRead|CFile::shareExclusive, &fe) &&
!p_pfr->CreateStream(lpRootStg, _T("Contents"),
CFile::modeRead|CFile::shareExclusive|CFile::modeCreate, &fe))
{
if (fe.m_cause == CFileException::fileNotFound)
AfxThrowArchiveException(CArchiveException::badSchema);
else
AfxThrowFileException(fe.m_cause, fe.m_lOsError);
}
// load it with CArchive (loads from Contents stream)
CArchive loadArchive(p_pfr, CArchive::load |
CArchive::bNoFlushOnDelete);
}
CATCH_ALL(e)
{
MessageBox(NULL,_T("Whoops"), _T("We did something bad."), MB_OK);
return false;
}
END_CATCH_ALL
return true;
}
Okay, so there is a fair amount of debugging left to do, and nevermind
the fact that the messagebox is completely uninformative or that I
haven't commented it, this appears to automatically handle the
variable size header information. I'll let you know as I test it
more.
~Scoots