Exemple #1
0
//*****************************************************************************
// This version will force the data in cache out to disk for real.  The code
// can handle the different types of storage we might be sitting on based on
// the open type.
//*****************************************************************************
HRESULT StgIO::WriteToDisk(             // Return code.
    const void  *pbBuff,                // Buffer to write.
    ULONG       cbWrite,                // How much.
    ULONG       *pcbWritten)            // Return how much written.
{
    ULONG       cbWritten;              // Buffer for write funcs.
    HRESULT     hr = S_OK;

    // Pretty obvious.
    _ASSERTE(!IsReadOnly());

    // Always need a buffer to write this data to.
    if (!pcbWritten)
        pcbWritten = &cbWritten;

    // Action taken depends on type of storage.
    switch (m_iType)
    {
        case STGIO_HFILE:
        case STGIO_HFILEMEM:
        {
            // Use the file system's move.
            _ASSERTE(m_hFile != INVALID_HANDLE_VALUE);

            // Do the write to disk.
            if (!::WriteFile(m_hFile, pbBuff, cbWrite, pcbWritten, 0))
                hr = MapFileError(GetLastError());
        }
        break;

        // Free the stream pointer.
        case STGIO_STREAM:
        {
            // Delegate write to stream code.
            hr = m_pIStream->Write(pbBuff, cbWrite, pcbWritten);
        }
        break;

        // We cannot write to fixed read/only memory or LoadLibrary module.
        case STGIO_HMODULE:
        case STGIO_MEM:
#ifndef FEATURE_METADATA_STANDALONE_WINRT_RO
        case STGIO_SHAREDMEM:
#endif
        _ASSERTE(0);
        hr = BadError(E_UNEXPECTED);
        break;

        // Weird to seek with no data.
        case STGIO_NODATA:
        default:
        _ASSERTE(0);
        break;
    }
    return (hr);
}
Exemple #2
0
//*****************************************************************************
// Convert a string to UNICODE into the caller's buffer.
//*****************************************************************************
HRESULT StgPoolReadOnly::GetStringW(      // Return code.
    ULONG       iOffset,                // Offset of string in pool.
    LPWSTR      szOut,                  // Output buffer for string.
    int         cchBuffer)              // Size of output buffer.
{
    LPCSTR      pString;                // The string in UTF8.
    int         iChars;
    pString = GetString(iOffset);
    iChars = ::WszMultiByteToWideChar(CP_UTF8, 0, pString, -1, szOut, cchBuffer);
    if (iChars == 0)
        return (BadError(HRESULT_FROM_NT(GetLastError())));
    return (S_OK);
}
Exemple #3
0
//*****************************************************************************
// Caller wants a pointer to a chunk of the file.  This function will make sure
// that the memory for that chunk has been committed and will load from the
// file if required.  This algorithm attempts to load no more data from disk
// than is necessary.  It walks the required pages from lowest to highest,
// and for each block of unloaded pages, the memory is committed and the data
// is read from disk.  If all pages are unloaded, all of them are loaded at
// once to speed throughput from disk.
//*****************************************************************************
HRESULT StgIO::GetPtrForMem(            // Return code.
    ULONG       cbStart,                // Where to start getting memory.
    ULONG       cbSize,                 // How much data.
    void        *&ptr)                  // Return pointer to memory here.
{
    int         iFirst, iLast;          // First and last page required.
    ULONG       iOffset, iSize;         // For committing ranges of memory.
    int         i, j;                   // Loop control.
    HRESULT     hr;

    // We need either memory (mmf or user supplied) or a backing store to
    // return a pointer.  Call Read if you don't have these.
    if (!IsBackingStore() && m_pData == 0)
        return (PostError(BadError(E_UNEXPECTED)));

    // Validate the caller isn't asking for a data value out of range.
    if (!(ClrSafeInt<ULONG>::addition(cbStart, cbSize, iOffset)
          && (iOffset <= m_cbData)))
        return (PostError(E_INVALIDARG));

    // This code will check for pages that need to be paged from disk in
    // order for us to return a pointer to that memory.
    if (IsBackingStore())
    {
        // Backing store is bogus when in rewrite mode.
        if (m_bRewrite)
            return (PostError(BadError(E_UNEXPECTED)));

        // Must have the page map to continue.
        _ASSERTE(m_rgPageMap && m_iPageSize && m_pData);

        // Figure out the first and last page that are required for commit.
        iFirst = cbStart / m_iPageSize;
        iLast = (cbStart + cbSize - 1) / m_iPageSize;

        // Avoid confusion.
        ptr = 0;

        // Do a smart load of every page required.  Do not reload pages that have
        // already been brought in from disk.
        //<REVISIT_TODO>@FUTURE: add an optimization so that when all pages have been faulted, we no
        // longer to a page by page search.</REVISIT_TODO>
        for (i=iFirst;  i<=iLast;  )
        {
            // Find the first page that hasn't already been loaded.
            while (GetBit(m_rgPageMap, i) && i<=iLast)
                ++i;
            if (i > iLast)
                break;

            // Offset for first thing to load.
            iOffset = i * m_iPageSize;
            iSize = 0;

            // See how many in a row have not been loaded.
            for (j=i;  i<=iLast && !GetBit(m_rgPageMap, i);  i++)
            {
                // Safe: iSize += m_iPageSize;
                if (!(ClrSafeInt<ULONG>::addition(iSize, m_iPageSize, iSize)))
                {
                    return PostError(E_INVALIDARG);
                }
            }

            // First commit the memory for this part of the file.
            if (::ClrVirtualAlloc((void *) ((DWORD_PTR) m_pData + iOffset), 
                    iSize, MEM_COMMIT, PAGE_READWRITE) == 0)
                return (PostError(OutOfMemory()));

            // Now load that portion of the file from disk.
            if (FAILED(hr = Seek(iOffset, FILE_BEGIN)) ||
                FAILED(hr = ReadFromDisk((void *) ((DWORD_PTR) m_pData + iOffset), iSize, 0)))
            {
                return (hr);
            }

            // Change the memory to read only to avoid any modifications.  Any faults
            // that occur indicate a bug whereby the engine is trying to write to
            // protected memory.
            _ASSERTE(::ClrVirtualAlloc((void *) ((DWORD_PTR) m_pData + iOffset), 
                    iSize, MEM_COMMIT, PAGE_READONLY) != 0);
        
            // Record each new loaded page.
            for (;  j<i;  j++)
                SetBit(m_rgPageMap, j, true);
        }

        // Everything was brought into memory, so now return pointer to caller.
        ptr = (void *) ((DWORD_PTR) m_pData + cbStart);
    }
    // Memory version or memory mapped file work the same way.
    else if (IsMemoryMapped() || 
             (m_iType == STGIO_MEM) || 
             (m_iType == STGIO_SHAREDMEM) || 
             (m_iType == STGIO_HFILEMEM))
    {   
        if (!(cbStart <= m_cbData))
            return (PostError(E_INVALIDARG));

        ptr = (void *) ((DWORD_PTR) m_pData + cbStart);
    }
    // What's left?!  Add some defense.
    else
    {
        _ASSERTE(0);
        ptr = 0;
        return (PostError(BadError(E_UNEXPECTED)));
    }
    return (S_OK);
}