//***************************************************************************** // 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; }
void DisplayArchive(wchar_t* szFile, ULONG DumpFilter, wchar_t* szObjName, strPassBackFn pDisplayString) { PBYTE pbMapAddress; PBYTE pbStartAddress; PBYTE pbLongNameAddress; PIMAGE_ARCHIVE_MEMBER_HEADER pMemHdr; DWORD dwFileSize; PVOID pvMetaData; char *szName; wchar_t wzName[1024]; char szBuf[17]; long cbMetaData; int i; HRESULT hr; char szString[1024]; GetMapViewOfFile(szFile, &pbMapAddress, &dwFileSize); pbStartAddress = pbMapAddress; // Verify and skip archive signature. if (dwFileSize < IMAGE_ARCHIVE_START_SIZE || strncmp((char *)pbMapAddress, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) { MDInfo::Error("Bad file format - archive signature mis-match!"); } pbMapAddress += IMAGE_ARCHIVE_START_SIZE; // Skip linker member 1, linker member 2. for (i = 0; i < 2; i++) pbMapAddress = SkipMember(pbMapAddress); // Save address of the long name member and skip it if there exists one. pMemHdr = (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress; if (pMemHdr->Name[0] == '/' && pMemHdr->Name[1] == '/') { pbLongNameAddress = pbMapAddress + IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR; pbMapAddress = SkipMember(pbMapAddress); } else pbLongNameAddress = 0; pDisplayString ("\n"); // Get the MetaData for each object file and display it. while (DWORD(pbMapAddress - pbStartAddress) < dwFileSize) { szName = GetNameOfObj(pbLongNameAddress, (PIMAGE_ARCHIVE_MEMBER_HEADER)pbMapAddress, szBuf); if (Wsz_mbstowcs(wzName, szName, 1024) == -1) MDInfo::Error("Conversion from Multi-Byte to Wide-Char failed."); // Display metadata only for object files. // If szObjName is specified, display metadata only for that one object file. if (!_stricmp(&szName[strlen(szName) - OBJ_EXT_LEN], OBJ_EXT) && (!szObjName || !_wcsicmp(szObjName, wzName))) { // Try to find the MetaData section in the current object file. hr = FindObjMetaData(pbMapAddress+IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR, &pvMetaData, &cbMetaData); if (SUCCEEDED(hr)) { sprintf (szString,"MetaData for object file %s:\n", szName); pDisplayString(szString); MDInfo archiveInfo(g_pDisp, (PBYTE)pvMetaData, cbMetaData, pDisplayString, DumpFilter); archiveInfo.DisplayMD(); } else { sprintf(szString,"MetaData not found for object file %s!\n\n", szName); pDisplayString(szString); } } // Skip past the object file. pbMapAddress = SkipMember(pbMapAddress); } UnmapViewOfFile(pbStartAddress); } // void DisplayArchive()
//***************************************************************************** // 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); }