//***************************************************************************** // 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
//***************************************************************************** // Open an in-memory metadata section for read //***************************************************************************** HRESULT CLiteWeightStgdbRW::InitOnMem( ULONG cbData, // count of bytes in pData LPCVOID pData, // points to meta data section in memory int bReadOnly) // If true, read-only. { StgIO *pStgIO = NULL; // For file i/o. HRESULT hr = NOERROR; if ((pStgIO = new (nothrow) StgIO) == 0) IfFailGo( E_OUTOFMEMORY); // Open the storage based on the pbData and cbData IfFailGo( pStgIO->Open( NULL, // filename STGIO_READ, pData, cbData, NULL, // IStream* NULL) // LPSecurityAttributes ); IfFailGo( InitFileForRead(pStgIO, bReadOnly) ); ErrExit: if (SUCCEEDED(hr)) { m_pStgIO = pStgIO; } else { if (pStgIO) pStgIO->Release(); } return hr; } // HRESULT CLiteWeightStgdbRW::InitOnMem()
//***************************************************************************** // 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()
//***************************************************************************** // 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
//***************************************************************************** // Open a metadata section for read //***************************************************************************** __checkReturn HRESULT CLiteWeightStgdbRW::OpenForRead( LPCWSTR szDatabase, // Name of database. void *pbData, // Data to open on top of, 0 default. ULONG cbData, // How big is the data. DWORD dwFlags) // Flags for the open. { LPCWSTR pNoFile=W(""); // Constant for empty file name. StgIO *pStgIO = NULL; // For file i/o. HRESULT hr; m_pImage = NULL; m_dwImageSize = 0; m_eFileType = FILETYPE_UNKNOWN; // szDatabase, and pbData are mutually exclusive. Only one may be // non-NULL. Having both NULL means empty stream creation. // _ASSERTE(!(szDatabase && (pbData))); _ASSERTE(!(pbData && (szDatabase))); // Open on memory needs there to be something to work with. if (pbData && cbData == 0) IfFailGo(CLDB_E_NO_DATA); // Make sure we have a path to work with. if (!szDatabase) szDatabase = pNoFile; // Sanity check the name lentgh. if (!IsValidFileNameLength(szDatabase)) { IfFailGo(E_INVALIDARG); } // If we have storage to work with, init it and get type. if (*szDatabase || pbData) { // Allocate a storage instance to use for i/o. if ((pStgIO = new (nothrow) StgIO) == 0) IfFailGo( E_OUTOFMEMORY ); DBPROPMODE dmOpenFlags = DBPROP_TMODEF_READ; // If we're taking ownership of this memory..... if (IsOfTakeOwnership(dwFlags)) { #ifdef FEATURE_METADATA_STANDALONE_WINRT_RO // Shared memory uses ole32.dll - we cannot depend on it in the standalone WinRT Read-Only DLL IfFailGo(E_INVALIDARG); #else dmOpenFlags = (DBPROPMODE)(dmOpenFlags | DBPROP_TMODEF_SHAREDMEM); #endif //!FEATURE_METADATA_STANDALONE_WINRT_RO } #ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES if (IsOfTrustedImage(dwFlags)) dmOpenFlags = (DBPROPMODE)(dmOpenFlags | DBPROP_TMODEF_TRYLOADLIBRARY); #endif // Open the storage so we can read the signature if there is already data. IfFailGo( pStgIO->Open(szDatabase, dmOpenFlags, pbData, cbData, 0, // IStream* NULL) ); // Determine the type of file we are working with. IfFailGo( _GetFileTypeForPath(pStgIO, &m_eFileType) ); } // Check for default type. if (m_eFileType == FILETYPE_CLB) { // If user wanted us to make a local copy of the data, do that now. if (IsOfCopyMemory(dwFlags)) IfFailGo(pStgIO->LoadFileToMemory()); // Try the native .clb file. IfFailGo( InitFileForRead(pStgIO, IsOfRead(dwFlags)) ); } // PE/COFF executable/object format. This requires us to find the .clb // inside the binary before doing the Init. else if (m_eFileType == FILETYPE_NTPE || m_eFileType == FILETYPE_NTOBJ) { //<TODO>@FUTURE: Ideally the FindImageMetaData function //@FUTURE: would take the pStgIO and map only the part of the file where //@FUTURE: our data lives, leaving the rest alone. This would be smaller //@FUTURE: working set for us.</TODO> void *ptr; ULONG cbSize; // Map the entire binary for the FindImageMetaData function. IfFailGo( pStgIO->MapFileToMem(ptr, &cbSize) ); // Find the .clb inside of the content. if (m_eFileType == FILETYPE_NTPE) { m_pImage = ptr; m_dwImageSize = cbSize; hr = FindImageMetaData(ptr, cbSize, pStgIO->GetMemoryMappedType() == MTYPE_IMAGE, &ptr, &cbSize); } else { _ASSERTE(pStgIO->GetMemoryMappedType() != MTYPE_IMAGE); hr = FindObjMetaData(ptr, cbSize, &ptr, &cbSize); } // Was the metadata found inside the PE file? if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) IfFailGo(E_OUTOFMEMORY); // No clb in the PE, assume it is a type library. m_eFileType = FILETYPE_TLB; // Let the caller deal with a TypeLib. IfFailGo(hr); } else { // Metadata was found inside the file. // Now reset the base of the stg object so that all memory accesses // are relative to the .clb content. // IfFailGo( pStgIO->SetBaseRange(ptr, cbSize) ); // If user wanted us to make a local copy of the data, do that now. if (IsOfCopyMemory(dwFlags)) { // Cache the PEKind, Machine. GetPEKind(pStgIO->GetMemoryMappedType(), NULL, NULL); // Copy the file into memory; releases the file. IfFailGo(pStgIO->LoadFileToMemory()); // No longer have the image. m_pImage = NULL; m_dwImageSize = 0; } // Defer to the normal lookup. IfFailGo( InitFileForRead(pStgIO, IsOfRead(dwFlags)) ); } } else if (m_eFileType == FILETYPE_TLB) { // Let the caller deal with a TypeLib. IfFailGo(CLDB_E_NO_DATA); } // This spells trouble, we need to handle all types we might find. else { _ASSERTE(!"Unknown file type."); IfFailGo( E_FAIL ); } // Save off everything. IfFailGo(SetFileName(szDatabase)); // If this was a file... if (pbData == NULL) { WIN32_FILE_ATTRIBUTE_DATA faData; if (!WszGetFileAttributesEx(szDatabase, GetFileExInfoStandard, &faData)) IfFailGo(E_FAIL); m_dwDatabaseLFS = faData.nFileSizeLow; m_dwDatabaseLFT = faData.ftLastWriteTime.dwLowDateTime; } ErrExit: if (SUCCEEDED(hr)) { m_pStgIO = pStgIO; } else { if (pStgIO != NULL) pStgIO->Release(); } return hr; }
//***************************************************************************** // Open a metadata section for read //***************************************************************************** HRESULT CLiteWeightStgdbRW::OpenForRead( LPCWSTR szDatabase, // Name of database. void *pbData, // Data to open on top of, 0 default. ULONG cbData, // How big is the data. IStream *pIStream, // Optional stream to use. LPCWSTR szSharedMem, // Shared memory name for read. int bReadOnly) // If true, read-only. { LPCWSTR pNoFile=L""; // Constant for empty file name. StgIO *pStgIO = NULL; // For file i/o. HRESULT hr; m_pImage = NULL; m_dwImageSize = 0; m_eFileType = FILETYPE_UNKNOWN; // szDatabase, pbData, and pIStream are mutually exclusive. Only one may be // non-NULL. Having all 3 NULL means empty stream creation. // _ASSERTE(!(szDatabase && (pbData || pIStream))); _ASSERTE(!(pbData && (szDatabase || pIStream))); _ASSERTE(!(pIStream && (szDatabase || pbData))); // Open on memory needs there to be something to work with. if (pbData && cbData == 0) IfFailGo(CLDB_E_NO_DATA); // Make sure we have a path to work with. if (!szDatabase) szDatabase = pNoFile; // Sanity check the name. if (lstrlenW(szDatabase) >= _MAX_PATH) IfFailGo( E_INVALIDARG ); // If we have storage to work with, init it and get type. if (*szDatabase || pbData || pIStream || szSharedMem) { // Allocate a storage instance to use for i/o. if ((pStgIO = new StgIO) == 0) IfFailGo( E_OUTOFMEMORY ); // Open the storage so we can read the signature if there is already data. IfFailGo( pStgIO->Open(szDatabase, STGIO_READ, pbData, cbData, pIStream, szSharedMem, NULL) ); // Determine the type of file we are working with. IfFailGo( _GetFileTypeForPath(pStgIO, &m_eFileType) ); } // Check for default type. if (m_eFileType == FILETYPE_CLB) { // Try the native .clb file. IfFailGo( InitFileForRead(pStgIO, bReadOnly) ); } // PE/COFF executable/object format. This requires us to find the .clb // inside the binary before doing the Init. else if (m_eFileType == FILETYPE_NTPE || m_eFileType == FILETYPE_NTOBJ) { void *ptr; ULONG cbSize; // Map the entire binary for the FindImageMetaData function. IfFailGo( pStgIO->MapFileToMem(ptr, &cbSize) ); // Find the .clb inside of the content. if (m_eFileType == FILETYPE_NTPE) { m_pImage = ptr; m_dwImageSize = cbSize; hr = FindImageMetaData(ptr, &ptr, &cbSize, cbSize); } else hr = FindObjMetaData(ptr, &ptr, &cbSize, cbSize); // Was the metadata found inside the PE file? if (FAILED(hr)) { // No clb in the PE, assume it is a type library. m_eFileType = FILETYPE_TLB; // Let the caller deal with a TypeLib. IfFailGo(CLDB_E_NO_DATA); } else { // Metadata was found inside the file. // Now reset the base of the stg object so that all memory accesses // are relative to the .clb content. // IfFailGo( pStgIO->SetBaseRange(ptr, cbSize) ); // Defer to the normal lookup. IfFailGo( InitFileForRead(pStgIO, bReadOnly) ); } } else if (m_eFileType == FILETYPE_TLB) { // Let the caller deal with a TypeLib. IfFailGo(CLDB_E_NO_DATA); } // This spells trouble, we need to handle all types we might find. else { _ASSERTE(!"Unknown file type."); IfFailGo( E_FAIL ); } // Save off everything. wcscpy(m_rcDatabase, szDatabase); ErrExit: if (SUCCEEDED(hr)) { m_pStgIO = pStgIO; } else { if (pStgIO) pStgIO->Release(); } return (hr); }