void cFCOPropTSTRING::Read(iSerializer* pSerializer, int32 version)
{
    if (version > 0)
        ThrowAndAssert(eSerializerVersionMismatch(_T("String Property Read")));

    pSerializer->ReadString( mValue );
}
void cFCOPropUint64::Read(iSerializer* pSerializer, int32 version)
{
    if (version > 0)
        ThrowAndAssert(eSerializerVersionMismatch(_T("uint64 Property Read")));

    pSerializer->ReadInt64((int64&)mValue);
}
void cFCOPropInt32::Read(iSerializer* pSerializer, int32 version)
{
    if (version > 0)
        ThrowAndAssert(eSerializerVersionMismatch(_T("Int32 Property Read")));

    pSerializer->ReadInt32(mValue);
}
void cFSObject::Read(iSerializer* pSerializer, int32 version)
{
	if (version > Version())
		ThrowAndAssert(eSerializerVersionMismatch(_T("File System Object")));

	
	pSerializer->ReadObject(&mName);
	pSerializer->ReadObject(&mPropSet);
}
void cFCOSpecImpl::Read(iSerializer* pSerializer, int32 version)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("FS Spec Read")));

    pSerializer->ReadString(mName);
    mPropVector.Read(pSerializer);

    // read the helper
    mpHelper = (iFCOSpecHelper*)pSerializer->ReadObjectDynCreate();
}
///////////////////////////////////////////////////////////////////////////////
// Read
///////////////////////////////////////////////////////////////////////////////
void cFCODatabaseFile::Read(iSerializer* pSerializer, int32 version)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("Database Read")));
    
    //
    // read the db header..
    //
    pSerializer->ReadObject( &mHeader );

    int32 numGenre;
    pSerializer->ReadInt32( numGenre );
    for( int i=0; i < numGenre; i++ )
    {
        // read the genre number and throw if it is incorrect
        //
        int32 iGenre;
        pSerializer->ReadInt32( iGenre );
        cGenre::Genre genre = (cGenre::Genre) iGenre;

        if( ! cGenreSwitcher::GetInstance()->IsGenreRegistered( genre ) )
        {
            throw eSerializerInputStreamFmt(_T("Encountered unknown genre.  Can not read database on this platform."), mFileName, eSerializer::TY_FILE);
        }

        mDbList.push_back( new tEntry( genre ) );
        tEntry& entry = *(mDbList.back());
        //
        // read the db genre header..
        //
        pSerializer->ReadObject( &entry.mGenreHeader );
        //
        // get the spec list
        //
        pSerializer->ReadObject( &entry.mSpecList );
        //
        // get the database data
        //
        int32 fileSize;
        pSerializer->ReadInt32( fileSize );
        //
        // write the hier database into a temp file...
        //
        cLockedTemporaryFileArchive* pArch = new cLockedTemporaryFileArchive();
        pArch->OpenReadWrite();

        cSerializerUtil::Copy( pArch, pSerializer, fileSize );
        //
        // associate the database with this file...
        //
        entry.mDb.Open( pArch );
    }
}
void cFSPropSet::Read(iSerializer* pSerializer, int32 version)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("FS Property Set Read")));

    mValidProps.Read(pSerializer);
    mUndefinedProps.Read(pSerializer);

    for (int i=0; i < PROP_NUMITEMS; i++)
    {
        if (mValidProps.ContainsItem(i) && !mUndefinedProps.ContainsItem(i))
            GetPropAt(i)->Read(pSerializer);
    }
}
void cHeaderInfo::Read(iSerializer* pSerializer, int32 version) // throw (eSerializer, eArchive)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("cHeaderInfo Read")));

    pSerializer->ReadString(tstr_SystemName);
    pSerializer->ReadString(tstr_PolicyFilename);
    pSerializer->ReadString(tstr_ConfigFilename);
    pSerializer->ReadString(tstr_DBFilename);
    pSerializer->ReadString(tstr_CommandLineParams);
    pSerializer->ReadString(tstr_CreatedBy);
    pSerializer->ReadString(tstr_IPAddress);
    pSerializer->ReadString(tstr_HostID);
    pSerializer->ReadInt64(i64_CreationTime);
    pSerializer->ReadInt64(i64_LastDBUpdateTime);
}
void cGenreHeaderInfo::Read(iSerializer* pSerializer, int32 version) // throw (eSerializer, eArchive)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("cHeaderInfo Read")));

    // read the prop displayer
    ASSERT(mpPropDisplayer == 0);

    int32 fMakePD;
    pSerializer->ReadInt32(fMakePD);

    if (fMakePD == 1)
        mpPropDisplayer = static_cast<iFCOPropDisplayer*>(pSerializer->ReadObjectDynCreate());

    pSerializer->ReadInt32(i32_ObjectsScanned);
}
///////////////////////////////////////////////////////////////////////////////
// AcceptSerializer 
///////////////////////////////////////////////////////////////////////////////
void cFCOSetImpl::Read(iSerializer* pSerializer, int32 version)
{
    if (version > Version())
        ThrowAndAssert(eSerializerVersionMismatch(_T("FCO Set Read")));

    Clear();

    int i;
    int32 size;
    pSerializer->ReadInt32(size);
    
    // TODO -- don't assert; throw an exception or noop -- mdb
    //ASSERT(size >= 0);

    for (i = 0; i < size; ++i)
    {
        iTypedSerializable* pObj = pSerializer->ReadObjectDynCreate();
        mFCOSet.insert(static_cast<iFCO*>(pObj));
    }
}
#endif

/// FSServices

TSS_REGISTER_ERROR( eFSServices(),       _T("File system error.") )
TSS_REGISTER_ERROR( eFSServicesGeneric(),_T("File system error.") )


/// Serializer

TSS_REGISTER_ERROR( eSerializerUnknownType(),           _T("Unknown type encountered in file.\nFile format may not be valid for this platform.") )
TSS_REGISTER_ERROR( eSerializerInputStreamFmt(),        _T("Invalid input stream format.") )
TSS_REGISTER_ERROR( eSerializerOutputStreamFmt(),       _T("Invalid output stream format.") )
TSS_REGISTER_ERROR( eSerializerInputStremTypeArray(),   _T("A bad index was encountered in file.") )
TSS_REGISTER_ERROR( eSerializerArchive(),               _T("File read encountered an archive error.") )
TSS_REGISTER_ERROR( eSerializerVersionMismatch(),       _T("File version mismatch.") )
TSS_REGISTER_ERROR( eSerializerEncryption(),            _T("File encryption error.") )
TSS_REGISTER_ERROR( eSerializer(),                      _T("File format error.") )


/// Command Line

TSS_REGISTER_ERROR( eCmdLine(),             _T("Command line parsing error.") )
TSS_REGISTER_ERROR( eCmdLineInvalidArg(),   _T("Invalid argument passed on command line.") )
TSS_REGISTER_ERROR( eCmdLineBadArgParam(),  _T("Incorrect number of parameters to a command line argument.") )
TSS_REGISTER_ERROR( eCmdLineBadParam(),     _T("Incorrect number of parameters on command line.") )
TSS_REGISTER_ERROR( eCmdLineBadSwitchPos(), _T("Switch appears after final command line parameter.") )
TSS_REGISTER_ERROR( eCmdLineMutEx(),        _T("Specified command line switches are mutually exclusive.") )
TSS_REGISTER_ERROR( eCmdLineDependency(),   _T("Command line parameter missing.") )
TSS_REGISTER_ERROR( eCmdLineMultiArg(),     _T("Command line argument specified more than once.") )
void cTWUtil::ReadConfigText(const TCHAR* filename, TSTRING& configText, cArchive* pBaggage)
{
    // TODO -- neat up this function; try to use LoadObject() above...

    cSerializableNString nstring;

    // This was coppied from ReadObject().  We need to use the baggage of the
    // file header to obtain the public key, thus the special casing.
    cDebug d("ReadConfigText");
    d.TraceDebug(_T("Reading %s from file %s\n"), nstring.GetType().AsString(), filename);

    iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE,
                                       _T("%s%s\n"),
                                       TSS_GetString(cTW, tw::STR_OPEN_CONFIG_FILE).c_str(),
                                       cDisplayEncoder::EncodeInline(filename).c_str());

    cFileArchive arch;
    arch.OpenRead(filename);

    cFileHeader fileHeader;

    try
    {
        cSerializerImpl fhSer(arch, cSerializerImpl::S_READ);
        fileHeader.Read(&fhSer);
    }
    catch (eError&)
    {
        throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE);
    }

#if 0 // XXX: This is broken, what the h*ll are they trying to write here? -PH
    d.TraceDebug("Found a file header of type %d.\n", fileHeader.GetEncoding());
#endif

    // check for a mismatched header
    if (fileHeader.GetID() != cConfigFile::GetFileHeaderID())
        throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE);

    // check the version
    if (fileHeader.GetVersion() != CURRENT_FIXED_VERSION)
        throw eSerializerVersionMismatch(_T(""), filename, eSerializer::TY_FILE);

    // switch on the type of encoding...
    if (fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION)
    {
        d.TraceDebug("Config file is compressed, public key len %d.\n", fileHeader.GetBaggage().Length());

        // tell the user the db is encrypted
        iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_FILE_ENCRYPTED).c_str());
        iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE, TSS_GetString(cTW, tw::STR_NEWLINE).c_str());

        ASSERT(fileHeader.GetBaggage().Length() > 0);
        if (fileHeader.GetBaggage().Length() <= 0)
            ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE));

        fileHeader.GetBaggage().MapArchive(0, fileHeader.GetBaggage().Length());

        cElGamalSigPublicKey publicKey(fileHeader.GetBaggage().GetMap());

        cElGamalSigArchive cryptoArchive;
        cryptoArchive.SetRead(&arch, &publicKey);

        cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ);
        ser.Init();
        ser.ReadObject(&nstring);
        ser.Finit();

        // copy the baggage into the archive, if it was passed in
        // Note: We rely in VerifySiteKey that we only fill out pBaggage if
        // the config file is encrypted.
        //
        if (pBaggage)
        {
            fileHeader.GetBaggage().Seek(0, cBidirArchive::BEGINNING);
            pBaggage->Copy(&fileHeader.GetBaggage(), fileHeader.GetBaggage().Length());
        }
    }
    else if (fileHeader.GetEncoding() == cFileHeader::COMPRESSED)
    {
        d.TraceDebug("Config file is not compressed.\n");

        //not encrypted db...
        cNullCryptoArchive cryptoArchive;
        cryptoArchive.Start(&arch);

        cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ);
        ser.Init();
        ser.ReadObject(&nstring);
        ser.Finit();
    }
    else
        // unknown encoding...
        throw eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE);

    // check 8 byte header
    if (nstring.mString.compare(0, 8 * sizeof(byte), CONFIG_FILE_MAGIC_8BYTE) != 0)
        ThrowAndAssert(eSerializerInputStreamFmt(_T(""), filename, eSerializer::TY_FILE));

    // remove 8 byte header
    nstring.mString.assign(nstring.mString.substr(8));

    cStringUtil::Convert(configText, nstring.mString);
}
///////////////////////////////////////////////////////////////////////////////
// WriteObjectToArchive -- called from WriteObject, does most of the work
///////////////////////////////////////////////////////////////////////////////
static void ReadObjectFromArchive(cArchive&                   arch,
                                  const TCHAR*                objFileName,
                                  iTypedSerializable*         pObjHeader,
                                  iTypedSerializable&         obj,
                                  const cFileHeaderID&        fhid,
                                  const cElGamalSigPublicKey* pPublicKey,
                                  bool&                       bEncrypted)
{
    cFileHeader fileHeader;

    {
        cSerializerImpl fhSer(arch, cSerializerImpl::S_READ, objFileName);
        fileHeader.Read(&fhSer);
    }

    // check for a mismatched header
    if (fileHeader.GetID() != fhid)
        ThrowAndAssert(eSerializerInputStreamFmt(_T(""), objFileName, eSerializer::TY_FILE));

    // Check file version.
    // If we in the future we wish to support reading objects of different versions,
    // we will have to move this check to outside ReadObject().
    if (fileHeader.GetVersion() != CURRENT_FIXED_VERSION)
        ThrowAndAssert(eSerializerVersionMismatch(_T(""), objFileName, eSerializer::TY_FILE));

    try
    {
        // switch on the type of encoding...
        if (fileHeader.GetEncoding() == cFileHeader::ASYM_ENCRYPTION)
        {
            // tell the user the db is encrypted
            iUserNotify::GetInstance()->Notify(iUserNotify::V_VERBOSE,
                                               TSS_GetString(cTW, tw::STR_FILE_ENCRYPTED).c_str());
            bEncrypted = true;

            if (pPublicKey == 0)
                ThrowAndAssert(eSerializerEncryption(_T("")));

            cElGamalSigArchive cryptoArchive;
            cryptoArchive.SetRead(&arch, pPublicKey);

            cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ, objFileName);
            ser.Init();
            if (pObjHeader)
                ser.ReadObject(pObjHeader);
            ser.ReadObject(&obj);
            ser.Finit();
        }
        else if (fileHeader.GetEncoding() == cFileHeader::COMPRESSED)
        {
            //not encrypted db...
            bEncrypted = false;

            cNullCryptoArchive cryptoArchive;
            cryptoArchive.Start(&arch);

            cSerializerImpl ser(cryptoArchive, cSerializerImpl::S_READ, objFileName);
            ser.Init();
            if (pObjHeader)
                ser.ReadObject(pObjHeader);
            ser.ReadObject(&obj);
            ser.Finit();
        }
        else
            // unknown encoding...
            ThrowAndAssert(eSerializerInputStreamFmt(_T("")));
    }
    catch (eError& e)
    {
        // include filename in error msg
        throw ePoly(e.GetID(), cErrorUtil::MakeFileError(e.GetMsg(), objFileName), e.GetFlags());
    }
}