Esempio n. 1
0
//*****************************************************************************
// 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;
}
Esempio n. 2
0
//*****************************************************************************
// 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);
}