示例#1
0
//*****************************************************************************
// Save the data to a stream.  A TiggerStorage sub-allocates streams within
//   the stream.
//*****************************************************************************
__checkReturn 
HRESULT CLiteWeightStgdbRW::SaveToStream(
    IStream                  *pIStream,
    MetaDataReorderingOptions reorderingOptions,
    CorProfileData           *pProfileData)
{
    HRESULT     hr = S_OK;              // A result.
    StgIO       *pStgIO = 0;
    TiggerStorage *pStorage = 0;
    
    // Allocate a storage subsystem and backing store.
    IfNullGo(pStgIO = new (nothrow) StgIO);
    IfNullGo(pStorage = new (nothrow) TiggerStorage);
    
    // Open around this stream for write.
    IfFailGo(pStgIO->Open(W(""), 
        DBPROP_TMODEF_DFTWRITEMASK, 
        0, 0,                           // pbData, cbData
        pIStream,
        0));                            // LPSecurityAttributes
    OptionValue ov;
    IfFailGo(m_MiniMd.GetOption(&ov));
    IfFailGo(pStorage->Init(pStgIO, ov.m_RuntimeVersion));
    
    // Save worker will do tables, pools.
    IfFailGo(SaveToStorage(pStorage, reorderingOptions, pProfileData));
    
ErrExit:
    if (pStgIO != NULL)
        pStgIO->Release();
    if (pStorage != NULL)
        delete pStorage;
    return hr;
} // CLiteWeightStgdbRW::SaveToStream
示例#2
0
//*****************************************************************************
// Save the metadata to a file.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::Save(       // S_OK or error.
    LPCWSTR     szDatabase,             // Name of file to which to save.
    DWORD       dwSaveFlags)            // Flags for the save.
{
    TiggerStorage *pStorage=0;          // IStorage object.
    StgIO       *pStgIO=0;              // Backing storage.
    HRESULT     hr = S_OK;

    if (!*m_rcDatabase)
    {
        if (!szDatabase)
        {
            // Make sure that a NULL is not passed in the first time around.
            _ASSERTE(!"Not allowed to pass a NULL for filename on the first call to Save.");
            return (E_INVALIDARG);
        }
        else
        {
            // Save the file name.
            wcscpy(m_rcDatabase, szDatabase);
        }
    }
    else if (szDatabase && _wcsicmp(szDatabase, m_rcDatabase) != 0)
    {
        // Allow for same name, case of multiple saves during session.
        // Changing the name on a scope which is already opened is not allowed.
        // Save the file name.
        wcscpy(m_rcDatabase, szDatabase);
    }

    // Sanity check the name.
    if (lstrlenW(m_rcDatabase) >= _MAX_PATH)
        IfFailGo(E_INVALIDARG);

    m_eFileType = FILETYPE_CLB;

    // Allocate a new storage object.
    IfNullGo(pStgIO = new StgIO);

    // Create the output file.
    IfFailGo(pStgIO->Open(m_rcDatabase, DBPROP_TMODEF_DFTWRITEMASK));

    // Allocate an IStorage object to use.
    IfNullGo(pStorage = new TiggerStorage);

    // Init the storage object on the i/o system.
    OptionValue ov;
    m_MiniMd.GetOption(&ov);
    IfFailGo( pStorage->Init(pStgIO, ov.m_RuntimeVersion) );

    // Save the data.
    IfFailGo(SaveToStorage(pStorage));

ErrExit:
    if (pStgIO)
        pStgIO->Release();
    if (pStorage)
        delete pStorage;
    return (hr);
} // HRESULT CLiteWeightStgdbRW::Save()
示例#3
0
//*****************************************************************************
// Save the data to a stream.  A TiggerStorage sub-allocates streams within
//   the stream.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::SaveToStream(
    IStream     *pIStream)
{
    HRESULT     hr = S_OK;              // A result.
    StgIO       *pStgIO = 0;
    TiggerStorage *pStorage = 0;

    // Allocate a storage subsystem and backing store.
    IfNullGo(pStgIO = new StgIO);
    IfNullGo(pStorage = new TiggerStorage);


    // Open around this stream for write.
    IfFailGo(pStgIO->Open(L"", DBPROP_TMODEF_DFTWRITEMASK, 0, 0, pIStream));
    OptionValue ov;
    m_MiniMd.GetOption(&ov);
    IfFailGo( pStorage->Init(pStgIO, ov.m_RuntimeVersion) );

    // Save worker will do tables, pools.
    IfFailGo(SaveToStorage(pStorage));

ErrExit:

    if (pStgIO)
        pStgIO->Release();
    if (pStorage)
        delete pStorage;
    return hr;
} // HRESULT CLiteWeightStgdbRW::PersistToStream()
示例#4
0
HRESULT RegMeta::OpenExistingMD(
    IMDCustomDataSource* pDataSource,   // Name of database.
    ULONG       dwOpenFlags)                // Flags to control open.
{
    HRESULT     hr = NOERROR;

    m_OpenFlags = dwOpenFlags;

    if (!IsOfReOpen(dwOpenFlags))
    {
        // Allocate our m_pStgdb, if we should.
        _ASSERTE(m_pStgdb == NULL);
        IfNullGo(m_pStgdb = new (nothrow)CLiteWeightStgdbRW);
    }

    IfFailGo(m_pStgdb->OpenForRead(
        pDataSource,
        m_OpenFlags));

    if (m_pStgdb->m_MiniMd.m_Schema.m_major == METAMODEL_MAJOR_VER_V1_0 &&
        m_pStgdb->m_MiniMd.m_Schema.m_minor == METAMODEL_MINOR_VER_V1_0)
        m_OptionValue.m_MetadataVersion = MDVersion1;

    else
        m_OptionValue.m_MetadataVersion = MDVersion2;



    IfFailGo(m_pStgdb->m_MiniMd.SetOption(&m_OptionValue));

    if (IsThreadSafetyOn())
    {
        m_pSemReadWrite = new (nothrow)UTSemReadWrite();
        IfNullGo(m_pSemReadWrite);
        IfFailGo(m_pSemReadWrite->Init());
        m_fOwnSem = true;

        INDEBUG(m_pStgdb->m_MiniMd.Debug_SetLock(m_pSemReadWrite);)
    }

    if (!IsOfReOpen(dwOpenFlags))
    {
#ifdef FEATURE_METADATA_EMIT_ALL
        // initialize the embedded merger
        m_newMerger.Init(this);
#endif //FEATURE_METADATA_EMIT_ALL

        // There must always be a Global Module class and its the first entry in
        // the TypeDef table.
        m_tdModule = TokenFromRid(1, mdtTypeDef);
    }

ErrExit:

    return hr;
} //RegMeta::OpenExistingMD
示例#5
0
//*****************************************************************************
// call stgdb InitNew
//*****************************************************************************
__checkReturn 
HRESULT 
RegMeta::CreateNewMD()
{
    HRESULT hr = NOERROR;
    
    m_OpenFlags = ofWrite;
    
    // Allocate our m_pStgdb.
    _ASSERTE(m_pStgdb == NULL);
    IfNullGo(m_pStgdb = new (nothrow) CLiteWeightStgdbRW);
    
    // Initialize the new, empty database.
    
    // First tell the new database what sort of metadata to create
    m_pStgdb->m_MiniMd.m_OptionValue.m_MetadataVersion = m_OptionValue.m_MetadataVersion;
    m_pStgdb->m_MiniMd.m_OptionValue.m_InitialSize = m_OptionValue.m_InitialSize;
    IfFailGo(m_pStgdb->InitNew());
    
    // Set up the Module record.
    ULONG      iRecord;
    ModuleRec *pModule;
    GUID       mvid;
    IfFailGo(m_pStgdb->m_MiniMd.AddModuleRecord(&pModule, &iRecord));
    IfFailGo(CoCreateGuid(&mvid));
    IfFailGo(m_pStgdb->m_MiniMd.PutGuid(TBL_Module, ModuleRec::COL_Mvid, pModule, mvid));
    
    // Add the dummy module typedef which we are using to parent global items.
    TypeDefRec *pRecord;
    IfFailGo(m_pStgdb->m_MiniMd.AddTypeDefRecord(&pRecord, &iRecord));
    m_tdModule = TokenFromRid(iRecord, mdtTypeDef);
    IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_TypeDef, TypeDefRec::COL_Name, pRecord, COR_WMODULE_CLASS));
    IfFailGo(m_pStgdb->m_MiniMd.SetOption(&m_OptionValue));
    
    if (IsThreadSafetyOn())
    {
        m_pSemReadWrite = new (nothrow) UTSemReadWrite();
        IfNullGo(m_pSemReadWrite);
        IfFailGo(m_pSemReadWrite->Init());
        m_fOwnSem = true;
        
        INDEBUG(m_pStgdb->m_MiniMd.Debug_SetLock(m_pSemReadWrite);)
    }
    
#ifdef FEATURE_METADATA_EMIT_ALL
    // initialize the embedded merger
    m_newMerger.Init(this);
#endif //FEATURE_METADATA_EMIT_ALL
    
ErrExit:
    return hr;
} // RegMeta::CreateNewMD
示例#6
0
//=======================================================================================
// 
// Set file name of this database (makes copy of the file name).
// 
// Return value: S_OK or E_OUTOFMEMORY
// 
__checkReturn 
HRESULT 
CLiteWeightStgdbRW::SetFileName(
    const WCHAR * wszFileName)
{
    HRESULT hr = S_OK;
    
    if (m_wszFileName != NULL)
    {
        delete [] m_wszFileName;
        m_wszFileName = NULL;
    }
    
    if ((wszFileName == NULL) || (*wszFileName == 0))
    {   // The new file name is empty
        _ASSERTE(m_wszFileName == NULL);
        
        // No need to allocate anything, NULL means empty name
        hr = S_OK;
        goto ErrExit;
    }
    
    // Size of the file name incl. null terminator
    size_t cchFileName;
    cchFileName = wcslen(wszFileName) + 1;
    
    // Allocate and copy the file name
    m_wszFileName = new (nothrow) WCHAR[cchFileName];
    IfNullGo(m_wszFileName);
    wcscpy_s(m_wszFileName, cchFileName, wszFileName);
    
ErrExit:
    return hr;
} // CLiteWeightStgdbRW::SetFileName
示例#7
0
STDMETHODIMP CCeeGen::AllocateMethodBuffer(ULONG cchBuffer, UCHAR **lpBuffer, ULONG *RVA)
{
    HRESULT hr = S_OK;
    BEGIN_ENTRYPOINT_NOTHROW;

    ULONG methodOffset = 0;

    if (! cchBuffer)
        IfFailGo(E_INVALIDARG);
    if (! lpBuffer || ! RVA)
        IfFailGo(E_POINTER);
    *lpBuffer = (UCHAR*) getIlSection().getBlock(cchBuffer, 4); // Dword align
    IfNullGo(*lpBuffer);

        // have to compute the method offset after getting the block, not
        // before (since alignment might shift it up 
    // for in-memory, just return address and will calc later
    methodOffset = getIlSection().dataLen() - cchBuffer;

    *RVA = methodOffset;

ErrExit:
    END_ENTRYPOINT_NOTHROW;

    return hr;
}
HRESULT CConnectProxy::FinalConstruct()
{
    HRESULT hr = S_OK;
    IUnknown* pUnkThis = NULL;

    // Instantiate the CLR-loader object.
    m_pCLRLoader = new (std::nothrow) CCLRLoader();
    IfNullGo( m_pCLRLoader );

    IfFailGo( this->QueryInterface(IID_IUnknown, (LPVOID*)&pUnkThis) );

    // Load the CLR, create an AppDomain, and instantiate the target add-in
    // and the inner aggregated object of the shim.
    IfFailGo( m_pCLRLoader->CreateAggregatedAddIn(
        pUnkThis,
        szAddInAssemblyName, szConnectClassName, szAssemblyConfigName) );

    // Extract the IDTExtensibility2 interface pointer from the target add-in.
    IfFailGo( m_pUnknownInner->QueryInterface(
        __uuidof(IDTExtensibility2), (LPVOID*)&this->m_pConnect) );

Error:
    if (pUnkThis != NULL)
        pUnkThis->Release();

    return hr;
}
示例#9
0
//*****************************************************************************
// Add a RegMeta pointer to the loaded module list
//*****************************************************************************
HRESULT LOADEDMODULES::AddModuleToLoadedList(RegMeta * pRegMeta)
{
    HRESULT    hr = NOERROR;
    RegMeta ** ppRegMeta;
    
    IfFailGo(InitializeStatics());
    
    {
        LOCKWRITE();
    
        ppRegMeta = s_pLoadedModules->Append();
        IfNullGo(ppRegMeta);
    
        // The cache holds a copy of the pointer, but no ref-count.  There is no
        //  point to the ref-count, because it just changes comparisons against 0
        //  to comparisons against 1.
        *ppRegMeta = pRegMeta;
    
        // If the module is read-only, hash it.
        if (pRegMeta->IsReadOnly())
        {
            ULONG ixHash = HashFileName(pRegMeta->GetNameOfDBFile());
            m_HashedModules[ixHash] = pRegMeta;
        }
    }
    
ErrExit:    
    return hr;
} // LOADEDMODULES::AddModuleToLoadedList
示例#10
0
//*****************************************************************************
// Called by the meta data engine when a token is remapped to a new location.
// This value is recorded in the m_rgMap array based on type and rid of the
// from token value.
//*****************************************************************************
HRESULT STDMETHODCALLTYPE CeeGenTokenMapper::Map(
    mdToken     tkFrom, 
    mdToken     tkTo)
{
    HRESULT hr = S_OK;
    mdToken *pToken = NULL;
    ULONG ridFrom = 0;
    TOKENMAP *pMap = NULL;

    BEGIN_ENTRYPOINT_NOTHROW;

    if ( IndexForType(tkFrom) == -1 )
    {
        // It is a type that we are not tracking, such as mdtProperty or mdtEvent,
        // just return S_OK.
        goto ErrExit;
    }

    _ASSERTE(IndexForType(tkFrom) < GetMaxMapSize());
    _ASSERTE(IndexForType(tkTo) != -1 && IndexForType(tkTo) < GetMaxMapSize());

    // If there is another token mapper that the user wants called, go
    // ahead and call it now.
    if (m_pIMapToken)
        m_pIMapToken->Map(tkFrom, tkTo);
    
    ridFrom = RidFromToken(tkFrom);
    pMap = &m_rgMap[IndexForType(tkFrom)];

    // If there isn't enough entries, fill out array up to the count
    // and mark the token to nil so we know there is no valid data yet.
    if ((ULONG) pMap->Count() <= ridFrom)
    {
        for (int i=ridFrom - pMap->Count() + 1;  i;  i--) 
        {
            pToken = pMap->Append();
            if (!pToken)
                break;
            *pToken = mdTokenNil;
        }
        _ASSERTE(!pToken || pMap->Get(ridFrom) == pToken);
    }
    else
        pToken = pMap->Get(ridFrom);

    IfNullGo(pToken);
    
    *pToken = tkTo;

ErrExit:
    END_ENTRYPOINT_NOTHROW;
    
    return hr;
}
示例#11
0
文件: mdutil.cpp 项目: ArildF/masters
//*****************************************************************************
// Add a RegMeta pointer to the loaded module list
//*****************************************************************************
HRESULT LOADEDMODULES::AddModuleToLoadedList(RegMeta *pRegMeta)
{
	HRESULT		hr = NOERROR;
	RegMeta		**ppRegMeta;

    LOCKWRITE();
    
	// create the dynamic array if it is not created yet.
	if (g_LoadedModules == NULL)
	{
		g_LoadedModules = new LOADEDMODULES;
        IfNullGo(g_LoadedModules);
	}

	ppRegMeta = g_LoadedModules->Append();
    IfNullGo(ppRegMeta);
	
	*ppRegMeta = pRegMeta;
    
ErrExit:    
    return hr;
}	// LOADEDMODULES::AddModuleToLoadedList
//*****************************************************************************
// Apply a delta record to a table, generically.
//*****************************************************************************
__checkReturn
HRESULT
CMiniMdRW::ApplyTableDelta(
    CMiniMdRW &mdDelta,     // Interface to MD with the ENC delta.
    ULONG      ixTbl,       // Table index to update.
    RID        iRid,        // RID of the changed item.
    int        fc)          // Function code of update.
{
    HRESULT hr = S_OK;
    void   *pRec;           // Record in existing MetaData.
    void   *pDeltaRec;      // Record if Delta MetaData.
    RID     newRid;         // Rid of new record.

    // Get the delta record.
    IfFailGo(mdDelta.GetDeltaRecord(ixTbl, iRid, &pDeltaRec));
    // Get the record from the base metadata.
    if (iRid > m_Schema.m_cRecs[ixTbl])
    {   // Added record.  Each addition is the next one.
        _ASSERTE(iRid == m_Schema.m_cRecs[ixTbl] + 1);
        switch (ixTbl)
        {
        case TBL_TypeDef:
            IfFailGo(AddTypeDefRecord(reinterpret_cast<TypeDefRec **>(&pRec), &newRid));
            break;
        case TBL_Method:
            IfFailGo(AddMethodRecord(reinterpret_cast<MethodRec **>(&pRec), &newRid));
            break;
        case TBL_EventMap:
            IfFailGo(AddEventMapRecord(reinterpret_cast<EventMapRec **>(&pRec), &newRid));
            break;
        case TBL_PropertyMap:
            IfFailGo(AddPropertyMapRecord(reinterpret_cast<PropertyMapRec **>(&pRec), &newRid));
            break;
        default:
            IfFailGo(AddRecord(ixTbl, &pRec, &newRid));
            break;
        }
        IfNullGo(pRec);
        _ASSERTE(iRid == newRid);
    }
    else
    {   // Updated record.
        IfFailGo(getRow(ixTbl, iRid, &pRec));
    }

    // Copy the record info.
    IfFailGo(ApplyRecordDelta(mdDelta, ixTbl, pDeltaRec, pRec));

ErrExit:
    return hr;
} // CMiniMdRW::ApplyTableDelta
示例#13
0
//*****************************************************************************
// Determine what the size of the saved data will be.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::GetSaveSize(// S_OK or error.
    CorSaveSize fSave,                  // Quick or accurate?
    ULONG       *pulSaveSize)           // Put the size here.
{
    HRESULT     hr = S_OK;              // A result.
    ULONG       cbTotal = 0;            // The total size.
    ULONG       cbSize = 0;             // Size of a component.

    m_cbSaveSize = 0;

    // Allocate stream list if not already done.
    if (!m_pStreamList)
        IfNullGo(m_pStreamList = new STORAGESTREAMLST);
    else
        m_pStreamList->Clear();

    // Query the MiniMd for its size.
    IfFailGo(GetTablesSaveSize(fSave, &cbSize));
    cbTotal += cbSize;

    // Get the pools' sizes.
    IfFailGo(GetPoolSaveSize(STRING_POOL_STREAM, MDPoolStrings, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(US_BLOB_POOL_STREAM, MDPoolUSBlobs, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(GUID_POOL_STREAM, MDPoolGuids, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(BLOB_POOL_STREAM, MDPoolBlobs, &cbSize));
    cbTotal += cbSize;

    // Finally, ask the storage system to add fixed overhead it needs for the
    // file format.  The overhead of each stream has already be calculated as
    // part of GetStreamSaveSize.  What's left is the signature and header
    // fixed size overhead.
    IfFailGo(TiggerStorage::GetStorageSaveSize(&cbTotal, 0));

    // Log the size info.
    LOG((LF_METADATA, LL_INFO10, "Metadata: GetSaveSize total is %d.\n", cbTotal));

    // The list of streams that will be saved are now in the stream save list.
    // Next step is to walk that list and fill out the correct offsets.  This is
    // done here so that the data can be streamed without fixing up the header.
    TiggerStorage::CalcOffsets(m_pStreamList, 0);

    if (pulSaveSize)
        *pulSaveSize = cbTotal;
    m_cbSaveSize = cbTotal;

ErrExit:
    return hr;
} // HRESULT CLiteWeightStgdbRW::GetSaveSize()
示例#14
0
//---------------------------------------------------------------------------------------
// 
// Initialize the static instance and lock.
// 
HRESULT 
LOADEDMODULES::InitializeStatics()
{
    HRESULT hr = S_OK;
    
    if (VolatileLoad(&s_pLoadedModules) == NULL)
    {
        // Initialize global read-write lock
        {
            NewHolder<UTSemReadWrite> pSemReadWrite = new (nothrow) UTSemReadWrite();
            IfNullGo(pSemReadWrite);
            IfFailGo(pSemReadWrite->Init());
            
            if (InterlockedCompareExchangeT<UTSemReadWrite *>(&m_pSemReadWrite, pSemReadWrite, NULL) == NULL)
            {   // We won the initialization race
                pSemReadWrite.SuppressRelease();
            }
        }
        
        // Initialize the global instance
        {
            NewHolder<LOADEDMODULES> pLoadedModules = new (nothrow) LOADEDMODULES();
            IfNullGo(pLoadedModules);
            
            {
                LOCKWRITE();
                
                if (VolatileLoad(&s_pLoadedModules) == NULL)
                {
                    VolatileStore(&s_pLoadedModules, pLoadedModules.Extract());
                }
            }
        }
    }
    
ErrExit:
    return hr;
} // LOADEDMODULES::InitializeStatics
//*****************************************************************************
//*****************************************************************************
__checkReturn
HRESULT
CMiniMdRW::StartENCMap()        // S_OK or error.
{
    HRESULT hr = S_OK;
    ULONG   iENC;               // Loop control.
    ULONG   ixTbl;              // A table.
    int     ixTblPrev = -1;     // Table previously seen.

    _ASSERTE(m_rENCRecs == 0);

    if (m_Schema.m_cRecs[TBL_ENCMap] == 0)
        return S_OK;

    // Build an array of pointers into the ENCMap table for fast access to the ENCMap
    //  for each table.
    m_rENCRecs = new (nothrow) ULONGARRAY;
    IfNullGo(m_rENCRecs);
    if (!m_rENCRecs->AllocateBlock(TBL_COUNT))
        IfFailGo(E_OUTOFMEMORY);
    for (iENC = 1; iENC <= m_Schema.m_cRecs[TBL_ENCMap]; ++iENC)
    {
        ENCMapRec *pMap;
        IfFailGo(GetENCMapRecord(iENC, &pMap));
        ixTbl = TblFromRecId(pMap->GetToken());
        _ASSERTE((int)ixTbl >= ixTblPrev);
        _ASSERTE(ixTbl < TBL_COUNT);
        _ASSERTE(ixTbl != TBL_ENCMap);
        _ASSERTE(ixTbl != TBL_ENCLog);
        if ((int)ixTbl == ixTblPrev)
            continue;
        // Catch up on any skipped tables.
        while (ixTblPrev < (int)ixTbl)
        {
            (*m_rENCRecs)[++ixTblPrev] = iENC;
        }
    }
    while (ixTblPrev < TBL_COUNT-1)
    {
        (*m_rENCRecs)[++ixTblPrev] = iENC;
    }

ErrExit:
    return hr;
} // CMiniMdRW::StartENCMap
//*****************************************************************************
// Add a stream, and its size, to the list of streams to be saved.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::AddStreamToList(
    ULONG       cbSize,
    LPCWSTR     szName)
{
    HRESULT     hr = S_OK;
    PSTORAGESTREAM pItem;               // New item to allocate & fill.

    // Add a new item to the end of the list.
    IfNullGo(pItem = m_pStreamList->Append());

    // Fill out the data.
    pItem->SetOffset(0);
    pItem->SetSize(cbSize);
    pItem->SetName(szName);

ErrExit:
    return hr;
}
示例#17
0
//*************************************************************
//
// Open the file with anme wzModule and check to see if there is a type 
// with namespace/class of wzNamespace/wzType. If so, return the RegMeta
// corresponding to the file and the mdTypeDef of the typedef
//
//*************************************************************
HRESULT CORPATHService::FindTypeDef(
    __in __in_z LPWSTR wzModule,    // name of the module that we are going to open
    mdTypeRef          tr,          // TypeRef to resolve.
    IMetaModelCommon * pCommon,     // Scope in which the TypeRef is defined.
    REFIID             riid, 
    IUnknown **        ppIScope,
    mdTypeDef *        ptd)         // [OUT] the type that we resolve to
{
    HRESULT                         hr = NOERROR;
    NewHolder<Disp>                 pDisp;
    ReleaseHolder<IMetaDataImport2> pImport = NULL;
    CQuickArray<mdTypeRef>          cqaNesters;
    CQuickArray<LPCUTF8>            cqaNesterNamespaces;
    CQuickArray<LPCUTF8>            cqaNesterNames;
    RegMeta *                       pRegMeta;
    
    _ASSERTE((ppIScope != NULL) && (ptd != NULL));
    
    *ppIScope = NULL;
    
    pDisp = new (nothrow) Disp;
    IfNullGo(pDisp);
    
    IfFailGo(pDisp->OpenScope(wzModule, 0, IID_IMetaDataImport2, (IUnknown **)&pImport));
    pRegMeta = static_cast<RegMeta *>(pImport.GetValue());
    
    // Get the Nesting hierarchy.
    IfFailGo(ImportHelper::GetNesterHierarchy(pCommon, tr, cqaNesters,
                                cqaNesterNamespaces, cqaNesterNames));

    hr = ImportHelper::FindNestedTypeDef(
                                pRegMeta->GetMiniMd(),
                                cqaNesterNamespaces,
                                cqaNesterNames,
                                mdTokenNil,
                                ptd);
    if (SUCCEEDED(hr))
    {
        *ppIScope = pImport.Extract();
    }
    
ErrExit:
    return hr;
} // CORPATHService::FindTypeDef
示例#18
0
文件: stgio.cpp 项目: A-And/coreclr
//*****************************************************************************
// Called to read the data into allocated memory and release the backing store.
//  Only available on read-only data.
//*****************************************************************************
HRESULT 
StgIO::LoadFileToMemory()
{
    HRESULT hr;
    void   *pData;          // Allocated buffer for file.
    ULONG   cbData;         // Size of the data.
    ULONG   cbRead = 0;     // Data actually read.
    
    // Make sure it is a read-only file.
    if (m_fFlags & DBPROP_TMODEF_WRITE)
        return E_INVALIDARG;
    
    // Try to allocate the buffer.
    cbData = m_cbData;
    pData = AllocateMemory(cbData);
    IfNullGo(pData);
    
    // Try to read the file into the buffer.
    IfFailGo(Read(pData, cbData, &cbRead));
    if (cbData != cbRead)
    {
        _ASSERTE_MSG(FALSE, "Read didn't succeed.");
        IfFailGo(CLDB_E_FILE_CORRUPT);
    }
    
    // Done with the old data.
    Close();
    
    // Open with new data.
    hr = Open(NULL /* szName */, STGIO_READ, pData, cbData, NULL /* IStream* */, NULL /* lpSecurityAttributes */);
    _ASSERTE(SUCCEEDED(hr)); // should not be a failure code path with open on buffer.
    
    // Mark the new memory so that it will be freed later.
    m_pBaseData = m_pData;
    m_bFreeMem = true;
    
ErrExit:
    if (FAILED(hr) && pData)
       FreeMemory(pData);
    
    return hr;
} // StgIO::LoadFileToMemory
示例#19
0
//*****************************************************************************
// Add a stream, and its size, to the list of streams to be saved.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::AddStreamToList(
    ULONG       cbSize,
    LPCWSTR     szName)
{
    HRESULT     hr = S_OK;
    STORAGESTREAM *pItem;               // New item to allocate & fill.
    int         size;

    // Add a new item to the end of the list.
    IfNullGo(pItem = m_pStreamList->Append());

    // Fill out the data.
    pItem->SetOffset(0);
    pItem->SetSize(cbSize);
    size = WszWideCharToMultiByte(CP_ACP, 0, szName, -1, pItem->rcName, MAXSTREAMNAME, 0, 0);
    _ASSERTE(size > 0);

ErrExit:
    return hr;
}
//*****************************************************************************
// Driver for the delta process.
//*****************************************************************************
__checkReturn
HRESULT
CMiniMdRW::ApplyDelta(
    CMiniMdRW &mdDelta) // Interface to MD with the ENC delta.
{
    HRESULT hr = S_OK;
    ULONG   iENC;       // Loop control.
    ULONG   iRid;       // RID of some record.
    ULONG   iNew;       // RID of a new record.
    int     i;          // Loop control.
    ULONG   ixTbl;      // A table.

#ifdef _DEBUG
    if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_ApplyDeltaBreak))
    {
        _ASSERTE(!"CMiniMDRW::ApplyDelta()");
    }
#endif // _DEBUG

    // Init the suppressed column table.  We know this one isn't zero...
    if (m_SuppressedDeltaColumns[TBL_TypeDef] == 0)
    {
        m_SuppressedDeltaColumns[TBL_EventMap]      = (1 << EventMapRec::COL_EventList);
        m_SuppressedDeltaColumns[TBL_PropertyMap]   = (1 << PropertyMapRec::COL_PropertyList);
        m_SuppressedDeltaColumns[TBL_EventMap]      = (1 << EventMapRec::COL_EventList);
        m_SuppressedDeltaColumns[TBL_Method]        = (1 << MethodRec::COL_ParamList);
        m_SuppressedDeltaColumns[TBL_TypeDef]       = (1 << TypeDefRec::COL_FieldList)|(1<<TypeDefRec::COL_MethodList);
    }

    // Verify the version of the MD.
    if (m_Schema.m_major != mdDelta.m_Schema.m_major ||
            m_Schema.m_minor != mdDelta.m_Schema.m_minor)
    {
        _ASSERTE(!"Version of Delta MetaData is a incompatible with current MetaData.");
        //<TODO>@FUTURE: unique error in the future since we are not shipping ENC.</TODO>
        return E_INVALIDARG;
    }

    // verify MVIDs.
    ModuleRec *pModDelta;
    ModuleRec *pModBase;
    IfFailGo(mdDelta.GetModuleRecord(1, &pModDelta));
    IfFailGo(GetModuleRecord(1, &pModBase));
    GUID GuidDelta;
    GUID GuidBase;
    IfFailGo(mdDelta.getMvidOfModule(pModDelta, &GuidDelta));
    IfFailGo(getMvidOfModule(pModBase, &GuidBase));
    if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) && (GuidDelta != GuidBase))
    {
        _ASSERTE(!"Delta MetaData has different base than current MetaData.");
        return E_INVALIDARG;
    }

#ifndef FEATURE_CORECLR
    // Verify that the delta is based on the base.
    IfFailGo(mdDelta.getEncBaseIdOfModule(pModDelta, &GuidDelta));
    IfFailGo(getEncBaseIdOfModule(pModBase,&GuidBase));
    if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) &&
            CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas) &&
            (GuidDelta != GuidBase))
    {
        _ASSERTE(!"The Delta MetaData is based on a different generation than the current MetaData.");
        return E_INVALIDARG;
    }
#endif //!FEATURE_CORECLR    

    // Let the other md prepare for sparse records.
    IfFailGo(mdDelta.StartENCMap());

    // Fix the heaps.
    IfFailGo(ApplyHeapDeltas(mdDelta));

    // Truncate some tables in preparation to copy in new ENCLog data.
    for (i = 0; (ixTbl = m_TruncatedEncTables[i]) != (ULONG)-1; ++i)
    {
        m_Tables[ixTbl].Delete();
        IfFailGo(m_Tables[ixTbl].InitializeEmpty_WithRecordCount(
                     m_TableDefs[ixTbl].m_cbRec,
                     mdDelta.m_Schema.m_cRecs[ixTbl]
                     COMMA_INDEBUG_MD(TRUE)));       // fIsReadWrite
        INDEBUG_MD(m_Tables[ixTbl].Debug_SetTableInfo(NULL, ixTbl));
        m_Schema.m_cRecs[ixTbl] = 0;
    }

    // For each record in the ENC log...
    for (iENC = 1; iENC <= mdDelta.m_Schema.m_cRecs[TBL_ENCLog]; ++iENC)
    {
        // Get the record, and the updated token.
        ENCLogRec *pENC;
        IfFailGo(mdDelta.GetENCLogRecord(iENC, &pENC));
        ENCLogRec *pENC2;
        IfFailGo(AddENCLogRecord(&pENC2, &iNew));
        IfNullGo(pENC2);
        ENCLogRec *pENC3;
        _ASSERTE(iNew == iENC);
        ULONG func = pENC->GetFuncCode();
        pENC2->SetFuncCode(pENC->GetFuncCode());
        pENC2->SetToken(pENC->GetToken());

        // What kind of record is this?
        if (IsRecId(pENC->GetToken()))
        {   // Non-token table
            iRid = RidFromRecId(pENC->GetToken());
            ixTbl = TblFromRecId(pENC->GetToken());
        }
        else
        {   // Token table.
            iRid = RidFromToken(pENC->GetToken());
            ixTbl = GetTableForToken(pENC->GetToken());
        }

        RID rid_Ignore;
        // Switch based on the function code.
        switch (func)
        {
        case eDeltaMethodCreate:
            // Next ENC record will define the new Method.
            MethodRec *pMethodRecord;
            IfFailGo(AddMethodRecord(&pMethodRecord, &rid_Ignore));
            IfFailGo(AddMethodToTypeDef(iRid, m_Schema.m_cRecs[TBL_Method]));
            break;

        case eDeltaParamCreate:
            // Next ENC record will define the new Param.  This record is
            //  tricky because params will be re-ordered based on their sequence,
            //  but the sequence isn't set until the NEXT record is applied.
            //  So, for ParamCreate only, apply the param record delta before
            //  adding the parent-child linkage.
            ParamRec *pParamRecord;
            IfFailGo(AddParamRecord(&pParamRecord, &rid_Ignore));

            // Should have recorded a Param delta after the Param add.
            _ASSERTE(iENC<mdDelta.m_Schema.m_cRecs[TBL_ENCLog]);
            IfFailGo(mdDelta.GetENCLogRecord(iENC+1, &pENC3));
            _ASSERTE(pENC3->GetFuncCode() == 0);
            _ASSERTE(GetTableForToken(pENC3->GetToken()) == TBL_Param);
            IfFailGo(ApplyTableDelta(mdDelta, TBL_Param, RidFromToken(pENC3->GetToken()), eDeltaFuncDefault));

            // Now that Param record is OK, set up linkage.
            IfFailGo(AddParamToMethod(iRid, m_Schema.m_cRecs[TBL_Param]));
            break;

        case eDeltaFieldCreate:
            // Next ENC record will define the new Field.
            FieldRec *pFieldRecord;
            IfFailGo(AddFieldRecord(&pFieldRecord, &rid_Ignore));
            IfFailGo(AddFieldToTypeDef(iRid, m_Schema.m_cRecs[TBL_Field]));
            break;

        case eDeltaPropertyCreate:
            // Next ENC record will define the new Property.
            PropertyRec *pPropertyRecord;
            IfFailGo(AddPropertyRecord(&pPropertyRecord, &rid_Ignore));
            IfFailGo(AddPropertyToPropertyMap(iRid, m_Schema.m_cRecs[TBL_Property]));
            break;

        case eDeltaEventCreate:
            // Next ENC record will define the new Event.
            EventRec *pEventRecord;
            IfFailGo(AddEventRecord(&pEventRecord, &rid_Ignore));
            IfFailGo(AddEventToEventMap(iRid, m_Schema.m_cRecs[TBL_Event]));
            break;

        case eDeltaFuncDefault:
            IfFailGo(ApplyTableDelta(mdDelta, ixTbl, iRid, func));
            break;

        default:
            _ASSERTE(!"Unexpected function in ApplyDelta");
            IfFailGo(E_UNEXPECTED);
            break;
        }
    }
    m_Schema.m_cRecs[TBL_ENCLog] = mdDelta.m_Schema.m_cRecs[TBL_ENCLog];

ErrExit:
    // Store the result for returning (IfFailRet will modify hr)
    HRESULT hrReturn = hr;
    IfFailRet(mdDelta.EndENCMap());

#ifndef FEATURE_CORECLR
    if (SUCCEEDED(hrReturn) &&
            CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_DeltaCheck) &&
            CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MD_UseMinimalDeltas))
    {
        GUID GuidNewBase;

        // We'll use the delta's 'delta guid' for our new base guid
        IfFailRet(mdDelta.getEncIdOfModule(pModDelta, &GuidNewBase));

        IfFailRet(PutGuid(TBL_Module, ModuleRec::COL_EncBaseId, pModBase, GuidNewBase));
    }
#endif //!FEATURE_CORECLR

    return hrReturn;
} // CMiniMdRW::ApplyDelta
//*****************************************************************************
// Determine what the size of the saved data will be.
//*****************************************************************************
HRESULT CLiteWeightStgdbRW::GetSaveSize(// S_OK or error.
    CorSaveSize fSave,                  // Quick or accurate?
    ULONG       *pulSaveSize,           // Put the size here.
    CorProfileData *profileData)        // Profile data for working set optimization
{
    HRESULT     hr = S_OK;              // A result.
    ULONG       cbTotal = 0;            // The total size.
    ULONG       cbSize = 0;             // Size of a component.

    m_cbSaveSize = 0;

    // Allocate stream list if not already done.
    if (!m_pStreamList)
        IfNullGo(m_pStreamList = new (nothrow) STORAGESTREAMLST);
    else
        m_pStreamList->Clear();

    // Make sure the user string pool is not empty. An empty user string pool causes
    // problems with edit and continue

    if(m_MiniMd.m_USBlobs.IsEmpty())
    {
        if(!(IsENCDelta(m_MiniMd.m_OptionValue.m_UpdateMode)||m_MiniMd.IsMinimalDelta()))
        {
            BYTE pbData[] = {' ', 0, 0};
            ULONG ulOffset;
            m_MiniMd.PutUserString(pbData,sizeof(pbData),&ulOffset);
        }
    }

    // If we're saving a delta metadata, figure out how much space it will take to
    // save the minimal metadata stream (used only to identify that we have a delta
    // metadata... nothing should be in that stream.
    if ((m_MiniMd.m_OptionValue.m_UpdateMode & MDUpdateMask) == MDUpdateDelta)
    {
        IfFailGo(AddStreamToList(0, MINIMAL_MD_STREAM));
        // Ask the storage system to add stream fixed overhead.
        IfFailGo(TiggerStorage::GetStreamSaveSize(MINIMAL_MD_STREAM, 0, &cbSize));
        cbTotal += cbSize;
    }


    // Query the MiniMd for its size.
    IfFailGo(GetTablesSaveSize(fSave, &cbSize, profileData));
    cbTotal += cbSize;

    // Get the pools' sizes.
    IfFailGo(GetPoolSaveSize(STRING_POOL_STREAM, MDPoolStrings, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(US_BLOB_POOL_STREAM, MDPoolUSBlobs, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(GUID_POOL_STREAM, MDPoolGuids, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(BLOB_POOL_STREAM, MDPoolBlobs, &cbSize));
    cbTotal += cbSize;

    // Finally, ask the storage system to add fixed overhead it needs for the
    // file format.  The overhead of each stream has already be calculated as
    // part of GetStreamSaveSize.  What's left is the signature and header
    // fixed size overhead.
    IfFailGo(TiggerStorage::GetStorageSaveSize(&cbTotal, 0, m_MiniMd.m_OptionValue.m_RuntimeVersion));

    // Log the size info.
    LOG((LF_METADATA, LL_INFO10, "Metadata: GetSaveSize total is %d.\n", cbTotal));
    
    // The list of streams that will be saved are now in the stream save list.
    // Next step is to walk that list and fill out the correct offsets.  This is 
    // done here so that the data can be streamed without fixing up the header.
    TiggerStorage::CalcOffsets(m_pStreamList, 0, m_MiniMd.m_OptionValue.m_RuntimeVersion);

    if (pulSaveSize)
        *pulSaveSize = cbTotal;

    // Don't cache the value for the EnC case
    if (!IsENCDelta(m_MiniMd.m_OptionValue.m_UpdateMode))
        m_cbSaveSize = cbTotal;

ErrExit:
    return hr;
} // HRESULT CLiteWeightStgdbRW::GetSaveSize()
示例#22
0
//*****************************************************************************
// Save the metadata to a file.
//*****************************************************************************
__checkReturn 
HRESULT CLiteWeightStgdbRW::Save(
    LPCWSTR szDatabase,     // Name of file to which to save.
    DWORD   dwSaveFlags)    // Flags for the save.
{
    TiggerStorage * pStorage = NULL;    // IStorage object.
    StgIO *         pStgIO = NULL;      // Backing storage.
    HRESULT         hr = S_OK;
    
    if (m_wszFileName == NULL)
    {
        if (szDatabase == NULL)
        {
            // Make sure that a NULL is not passed in the first time around.
            _ASSERTE(!"Not allowed to pass a NULL for filename on the first call to Save.");
            return E_INVALIDARG;
        }
        else
        {
            // Save the file name.
            IfFailGo(SetFileName(szDatabase));
        }
    }
    else if ((szDatabase != NULL) && (SString::_wcsicmp(szDatabase, m_wszFileName) != 0))
    {
        // Save the file name.
        IfFailGo(SetFileName(szDatabase));
    }
    
    // Sanity check the name.
    if (!IsValidFileNameLength(m_wszFileName))
    {
        IfFailGo(E_INVALIDARG);
    }
    
    m_eFileType = FILETYPE_CLB;
    
    // Allocate a new storage object.
    IfNullGo(pStgIO = new (nothrow) StgIO);
    
    // Create the output file.
    IfFailGo(pStgIO->Open(m_wszFileName, 
        DBPROP_TMODEF_DFTWRITEMASK,
        0,0,                // pbData, cbData
        0,                  // IStream*
        0));                // LPSecurityAttributes
    
    // Allocate an IStorage object to use.
    IfNullGo(pStorage = new (nothrow) TiggerStorage);
    
    // Init the storage object on the i/o system.
    OptionValue ov;
    IfFailGo(m_MiniMd.GetOption(&ov));
    IfFailGo(pStorage->Init(pStgIO, ov.m_RuntimeVersion));
    
    // Save the data.
    IfFailGo(SaveToStorage(pStorage));
    
ErrExit:
    if (pStgIO != NULL)
        pStgIO->Release();
    if (pStorage != NULL)
        delete pStorage;
    return hr;
} // CLiteWeightStgdbRW::Save
示例#23
0
//*****************************************************************************
// Determine what the size of the saved data will be.
//*****************************************************************************
__checkReturn 
HRESULT CLiteWeightStgdbRW::GetSaveSize(// S_OK or error.
    CorSaveSize               fSave,                // Quick or accurate?
    UINT32                   *pcbSaveSize,          // Put the size here.
    MetaDataReorderingOptions reorderingOptions,
    CorProfileData           *pProfileData)        // Profile data for working set optimization
{
    HRESULT hr = S_OK;              // A result.
    UINT32  cbTotal = 0;            // The total size.
    UINT32  cbSize = 0;             // Size of a component.
    
    m_cbSaveSize = 0;
    
    // Allocate stream list if not already done.
    if (m_pStreamList == NULL)
    {
        IfNullGo(m_pStreamList = new (nothrow) STORAGESTREAMLST);
    }
    else
    {
        m_pStreamList->Clear();
    }
    
    // Make sure the user string pool is not empty. An empty user string pool causes
    // problems with edit and continue
    
    if (m_MiniMd.m_UserStringHeap.GetUnalignedSize() <= 1)
    {
        if (!IsENCDelta(m_MiniMd.m_OptionValue.m_UpdateMode) && 
            !m_MiniMd.IsMinimalDelta())
        {
            BYTE   rgData[] = {' ', 0, 0};
            UINT32 nIndex_Ignore;
            IfFailGo(m_MiniMd.PutUserString(
                MetaData::DataBlob(rgData, sizeof(rgData)), 
                &nIndex_Ignore));
        }
    }
    
    // If we're saving a delta metadata, figure out how much space it will take to
    // save the minimal metadata stream (used only to identify that we have a delta
    // metadata... nothing should be in that stream.
    if ((m_MiniMd.m_OptionValue.m_UpdateMode & MDUpdateMask) == MDUpdateDelta)
    {
        IfFailGo(AddStreamToList(0, MINIMAL_MD_STREAM));
        // Ask the storage system to add stream fixed overhead.
        IfFailGo(TiggerStorage::GetStreamSaveSize(MINIMAL_MD_STREAM, 0, &cbSize));
        cbTotal += cbSize;
    }
    
    if (reorderingOptions & ReArrangeStringPool)
    {
        if (pProfileData != NULL)
        {
            UINT32 cbHotSize = 0;          // Size of pool data.
            UINT32 cbStream;               // Size of just the stream.
            DWORD  bCompressed;            // Will the stream be compressed data?
            
            // Ask the metadata to size its hot data.
            IfFailGo(m_MiniMd.GetSaveSize(fSave, &cbHotSize, &bCompressed, reorderingOptions, pProfileData));
            cbStream = cbHotSize;
            m_bSaveCompressed = bCompressed;
            
            if (cbHotSize != 0)
            {
                // Add this item to the save list.
                IfFailGo(AddStreamToList(cbHotSize, HOT_MODEL_STREAM));
                
                // Ask the storage system to add stream fixed overhead.
                IfFailGo(TiggerStorage::GetStreamSaveSize(HOT_MODEL_STREAM, cbHotSize, &cbHotSize));
                
                // Log the size info.
                LOG((LF_METADATA, LL_INFO10, "Metadata: GetSaveSize for %ls: %d data, %d total.\n",
                    HOT_MODEL_STREAM, cbStream, cbHotSize));
                
                cbTotal += cbHotSize;
            }
        }
        
        // get string pool save size
        IfFailGo(GetPoolSaveSize(STRING_POOL_STREAM, MDPoolStrings, &cbSize));
        cbTotal += cbSize;
    }
    
    // Query the MiniMd for its size.
    IfFailGo(GetTablesSaveSize(fSave, &cbSize, reorderingOptions, pProfileData));
    cbTotal += cbSize;
    
    // Get the pools' sizes.
    if( !(reorderingOptions & ReArrangeStringPool) )
    {
        IfFailGo(GetPoolSaveSize(STRING_POOL_STREAM, MDPoolStrings, &cbSize));
        cbTotal += cbSize;
    }
    IfFailGo(GetPoolSaveSize(US_BLOB_POOL_STREAM, MDPoolUSBlobs, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(GUID_POOL_STREAM, MDPoolGuids, &cbSize));
    cbTotal += cbSize;
    IfFailGo(GetPoolSaveSize(BLOB_POOL_STREAM, MDPoolBlobs, &cbSize));
    cbTotal += cbSize;
    
    // Finally, ask the storage system to add fixed overhead it needs for the
    // file format.  The overhead of each stream has already be calculated as
    // part of GetStreamSaveSize.  What's left is the signature and header
    // fixed size overhead.
    IfFailGo(TiggerStorage::GetStorageSaveSize((ULONG *)&cbTotal, 0, m_MiniMd.m_OptionValue.m_RuntimeVersion));
    
    // Log the size info.
    LOG((LF_METADATA, LL_INFO10, "Metadata: GetSaveSize total is %d.\n", cbTotal));
    
    // The list of streams that will be saved are now in the stream save list.
    // Next step is to walk that list and fill out the correct offsets.  This is 
    // done here so that the data can be streamed without fixing up the header.
    TiggerStorage::CalcOffsets(m_pStreamList, 0, m_MiniMd.m_OptionValue.m_RuntimeVersion);
    
    if (pcbSaveSize != NULL)
    {
        *pcbSaveSize = cbTotal;
    }
    
    // Don't cache the value for the EnC case
    if (!IsENCDelta(m_MiniMd.m_OptionValue.m_UpdateMode))
        m_cbSaveSize = cbTotal;
    
ErrExit:
    return hr;
} // CLiteWeightStgdbRW::GetSaveSize
示例#24
0
//*****************************************************************************
// Given an StgIO, opens compressed streams and do proper initialization.
// This is a helper for other Init functions.
//*****************************************************************************
__checkReturn 
HRESULT 
CLiteWeightStgdbRW::InitFileForRead(
    StgIO * pStgIO,     // For file i/o.
    int     bReadOnly)  // If read-only open.
{
    TiggerStorage * pStorage = NULL;
    void          * pvData;
    ULONG           cbData;
    HRESULT         hr = NOERROR;
    
    // Allocate a new storage object which has IStorage on it.
    pStorage = new (nothrow) TiggerStorage();
    IfNullGo(pStorage);
    
    // Init the storage object on the backing storage.
    OptionValue ov;
    IfFailGo(m_MiniMd.GetOption(&ov));
    IfFailGo(pStorage->Init(pStgIO, ov.m_RuntimeVersion));
    
    // Save pointers to header structure for version string.
    _ASSERTE((m_pvMd == NULL) && (m_cbMd == 0));
    IfFailGo(pStorage->GetHeaderPointer(&m_pvMd, &m_cbMd));
    
    // Check to see if this is a minimal metadata
    if (SUCCEEDED(pStorage->OpenStream(MINIMAL_MD_STREAM, &cbData, &pvData)))
    {
        m_MiniMd.m_fMinimalDelta = TRUE;
    }
    
    // Load the string pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(STRING_POOL_STREAM, &cbData, &pvData)))
    {
        // String pool has to end with a null-terminator, therefore we don't have to check string pool 
        // content on access.
        // Shrink size of the pool to the last null-terminator found.
        while (cbData != 0)
        {
            if (((LPBYTE)pvData)[cbData - 1] == 0)
            {   // We have found last null terminator
                break;
            }
            // Shrink size of the pool
            cbData--;
            Debug_ReportError("String heap/pool does not end with null-terminator ... shrinking the heap.");
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolStrings, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolStrings, NULL, 0, bReadOnly));
    }
    
    // Load the user string blob pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(US_BLOB_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolUSBlobs, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolUSBlobs, NULL, 0, bReadOnly));
    }
    
    // Load the guid pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(GUID_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolGuids, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolGuids, NULL, 0, bReadOnly));
    }
    
    // Load the blob pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(BLOB_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolBlobs, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolBlobs, NULL, 0, bReadOnly));
    }
    
    // Open the metadata.
    hr = pStorage->OpenStream(COMPRESSED_MODEL_STREAM, &cbData, &pvData);
    if (hr == STG_E_FILENOTFOUND)
    {
        IfFailGo(pStorage->OpenStream(ENC_MODEL_STREAM, &cbData, &pvData));
    }
    IfFailGo(m_MiniMd.InitOnMem(pvData, cbData, bReadOnly));
    IfFailGo(m_MiniMd.PostInit(0));
    
ErrExit:
    if (pStorage != NULL)
    {
        delete pStorage;
    }
    return hr;
} // CLiteWeightStgdbRW::InitFileForRead
示例#25
0
//*****************************************************************************
// IGetIMDInternalImport methods
//*****************************************************************************
HRESULT RegMeta::GetIMDInternalImport(
        IMDInternalImport ** ppIMDInternalImport   // [OUT] Buffer to receive IMDInternalImport*
    )
{
    HRESULT       hr = S_OK;
    MDInternalRW *pInternalRW = NULL;
    bool          isLockedForWrite = false;
    IUnknown     *pIUnkInternal = NULL;
    IUnknown     *pThis = (IMetaDataImport2*)this;  

    pIUnkInternal = this->GetCachedInternalInterface(TRUE);
    if (pIUnkInternal)
    {
        // there is already a cached Internal interface. GetCachedInternalInterface does add ref the 
        // returned interface 
        IfFailGo(pIUnkInternal->QueryInterface(IID_IMDInternalImport, (void**)ppIMDInternalImport));
        goto ErrExit;
    }

    if (this->IsThreadSafetyOn())
    {
        _ASSERTE( this->GetReaderWriterLock() );
        IfFailGo(this->GetReaderWriterLock()->LockWrite());
        isLockedForWrite = true;
    }

    // check again. Maybe someone else beat us to setting the internal interface while we are waiting
    // for the write lock. Don't need to grab the read lock since we already have the write lock.
    pIUnkInternal = this->GetCachedInternalInterface(FALSE);
    if (pIUnkInternal)
    {
        // there is already a cached Internal interface. GetCachedInternalInterface does add ref the 
        // returned interface 
        IfFailGo(pIUnkInternal->QueryInterface(IID_IMDInternalImport, (void**)ppIMDInternalImport));
        goto ErrExit;
    }
        
    // now create the compressed object
    IfNullGo( pInternalRW = new (nothrow) MDInternalRW );
    IfFailGo( pInternalRW->InitWithStgdb(pThis, this->GetMiniStgdb() ) );

    // make the public object and the internal object point to each other.
    _ASSERTE( pInternalRW->GetReaderWriterLock() == NULL && 
              (! this->IsThreadSafetyOn() || this->GetReaderWriterLock() != NULL ));
    IfFailGo( this->SetCachedInternalInterface(static_cast<IMDInternalImportENC*>(pInternalRW)) );
    IfFailGo( pInternalRW->SetCachedPublicInterface(pThis));
    IfFailGo( pInternalRW->SetReaderWriterLock(this->GetReaderWriterLock() ));
    IfFailGo( pInternalRW->QueryInterface(IID_IMDInternalImport, (void**)ppIMDInternalImport));

ErrExit:
    if (isLockedForWrite == true)
        this->GetReaderWriterLock()->UnlockWrite();
    if (pIUnkInternal)
        pIUnkInternal->Release();
    if (pInternalRW)
        pInternalRW->Release();
    if (FAILED(hr))
    {
        if (ppIMDInternalImport)
            *ppIMDInternalImport = 0;
    }
    return hr;
}
示例#26
0
//*****************************************************************************
// GetMDInternalInterface.
// This function will check the metadata section and determine if it should
// return an interface which implements ReadOnly or ReadWrite.
//*****************************************************************************
STDAPI GetMDInternalInterface(
    LPVOID      pData, 
    ULONG       cbData, 
    DWORD       flags,                  // [IN] ofRead or ofWrite.
    REFIID      riid,                   // [in] The interface desired.
    void        **ppIUnk)               // [out] Return interface on success.
{
    HRESULT     hr = NOERROR;
    MDInternalRO *pInternalRO = NULL;
    IMDCommon    *pInternalROMDCommon = NULL;
    MDFileFormat format;

    BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);

    if (ppIUnk == NULL)
        IfFailGo(E_INVALIDARG);

    // Determine the file format we're trying to read.
    IfFailGo( CheckFileFormat(pData, cbData, &format) );

    // Found a fully-compressed, read-only format.
    if ( format == MDFormat_ReadOnly )
    {
        pInternalRO = new (nothrow) MDInternalRO;
        IfNullGo( pInternalRO );

        IfFailGo( pInternalRO->Init(const_cast<void*>(pData), cbData) );

#ifdef FEATURE_COMINTEROP
        IfFailGo(pInternalRO->QueryInterface(IID_IMDCommon, (void**)&pInternalROMDCommon));
        IfFailGo( (flags & ofNoTransform) ? S_FALSE : CheckIfWinMDAdapterNeeded(pInternalROMDCommon));
        if (hr == S_OK)
        {
            IfFailGo(CreateWinMDInternalImportRO(pInternalROMDCommon, riid, (void**)ppIUnk));
        }
        else
#endif // FEATURE_COMINTEROP
        {
            IfFailGo(pInternalRO->QueryInterface(riid, ppIUnk));
        }

    }
    else
    {
        // Found a not-fully-compressed, ENC format.
        _ASSERTE( format == MDFormat_ReadWrite );
        IfFailGo( GetInternalWithRWFormat( pData, cbData, flags, riid, ppIUnk ) );
    }

ErrExit:

    // clean up
    if ( pInternalRO )
        pInternalRO->Release();
    if ( pInternalROMDCommon )
        pInternalROMDCommon->Release();

    END_SO_INTOLERANT_CODE;
    
    return hr;
}   // GetMDInternalInterface
示例#27
0
//*****************************************************************************
// Using the existing RegMeta and reopen with another chuck of memory. Make sure that all stgdb
// is still kept alive.
//*****************************************************************************
HRESULT RegMeta::ReOpenWithMemory(
    LPCVOID     pData,                  // [in] Location of scope data.
    ULONG       cbData,                 // [in] Size of the data pointed to by pData.
    DWORD       dwReOpenFlags)           // [in] ReOpen flags
{
    HRESULT hr = NOERROR;

    // Only allow the ofCopyMemory and ofTakeOwnership flags 
    if (dwReOpenFlags != 0 && ((dwReOpenFlags & (~(ofCopyMemory|ofTakeOwnership))) > 0))
        return E_INVALIDARG;

    LOCKWRITE();

    
    // put the current m_pStgdb to the free list
    m_pStgdb->m_pNextStgdb = m_pStgdbFreeList;
    m_pStgdbFreeList = m_pStgdb;
    m_pStgdb = new (nothrow) CLiteWeightStgdbRW;
    IfNullGo( m_pStgdb );
    IfFailGo( OpenExistingMD(0 /* szFileName */, const_cast<void*>(pData), cbData, ofReOpen|dwReOpenFlags /* flags */) );

#ifdef FEATURE_METADATA_INTERNAL_APIS
    // We've created a new Stgdb, but may still have an Internal Importer hanging around accessing the old Stgdb.
    // The free list ensures we don't have a dangling pointer, but the 
    // If we have a corresponding InternalInterface, need to clear it because it's now using stale data.
    // Others will need to update their Internal interface to get the new data.
    {
        HRESULT hrIgnore = SetCachedInternalInterface(NULL);
        (void)hrIgnore; //prevent "unused variable" error from GCC
        _ASSERTE(hrIgnore == NOERROR); // clearing the cached interface should always succeed.
    }
#endif //FEATURE_METADATA_INTERNAL_APIS

    // we are done!
ErrExit:
    if (FAILED(hr))
    {
        // recover to the old state
        if (m_pStgdb)
            delete m_pStgdb;
        m_pStgdb = m_pStgdbFreeList;
        m_pStgdbFreeList = m_pStgdbFreeList->m_pNextStgdb;
    }
#ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN
    else
    {
        if( !(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_MD_PreserveDebuggerMetadataMemory)) && IsSafeToDeleteStgdb())
        {
            // now that success is assured, delete the old block of memory
            // This isn't normally a safe operation because we would have given out
            // internal pointers to the memory. However when this feature is enabled
            // we track calls that might have given out internal pointers. If none
            // of the APIs were ever called then we can safely delete.
            CLiteWeightStgdbRW* pStgdb = m_pStgdbFreeList;
            m_pStgdbFreeList = m_pStgdbFreeList->m_pNextStgdb;
            delete pStgdb;
        }

        MarkSafeToDeleteStgdb(); // As of right now, no APIs have given out internal pointers
                                 // to the newly allocated stgdb
    }
#endif

    return hr;
} // RegMeta::ReOpenWithMemory