/// 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.") )

///////////////////////////////////////////////////////////////////////////////
// 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());
    }
}