// -------------------------------------------------------------------------------- // Ibdylock.cpp // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved // Steven J. Bailey // -------------------------------------------------------------------------------- #include "pch.hxx" #ifndef WIN16 #include "ibdylock.h" #endif // !WIn16 #include "stmlock.h" #include "booktree.h" #ifdef WIN16 #include "ibdylock.h" #endif // WIn16 #include "demand.h" // -------------------------------------------------------------------------------- // CBodyLockBytes::CBodyLockBytes // -------------------------------------------------------------------------------- CBodyLockBytes::CBodyLockBytes(ILockBytes *pLockBytes, LPTREENODEINFO pNode) { // Invalid ARg Assert(pLockBytes && pNode); // Set Initialize Ref Count and State m_cRef = 1; m_dwState = 0; // AddRef the LockBytes m_pLockBytes = pLockBytes; m_pLockBytes->AddRef(); // Save State FLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE); // Save the bind state m_bindstate = pNode->bindstate; // Save body start and body end.. Assert(pNode->cbBodyStart <= pNode->cbBodyEnd); // Save Body Start #ifdef MAC ULISet32(m_uliBodyStart, pNode->cbBodyStart); ULISet32(m_uliBodyEnd, pNode->cbBodyEnd); // This condition is here to insure that we don't have a problem... if (m_uliBodyStart.LowPart > m_uliBodyEnd.LowPart) m_uliBodyStart.LowPart = m_uliBodyEnd.LowPart; #else // !MAC m_uliBodyStart.QuadPart = pNode->cbBodyStart; m_uliBodyEnd.QuadPart = pNode->cbBodyEnd; // This condition is here to insure that we don't have a problem... if (m_uliBodyStart.QuadPart > m_uliBodyEnd.QuadPart) m_uliBodyStart.QuadPart = m_uliBodyEnd.QuadPart; #endif // MAC // Initialize the CriticalSection InitializeCriticalSection(&m_cs); } // -------------------------------------------------------------------------------- // CBodyLockBytes::~CBodyLockBytes // -------------------------------------------------------------------------------- CBodyLockBytes::~CBodyLockBytes(void) { SafeRelease(m_pLockBytes); Assert(!ISFLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE)); DeleteCriticalSection(&m_cs); } // -------------------------------------------------------------------------------- // CBodyLockBytes::QueryInterface // -------------------------------------------------------------------------------- STDMETHODIMP CBodyLockBytes::QueryInterface(REFIID riid, LPVOID *ppv) { // check params if (ppv == NULL) return TrapError(E_INVALIDARG); // Init *ppv = NULL; // Find IID if (IID_IUnknown == riid) *ppv = (IUnknown *)this; else if (IID_ILockBytes == riid) *ppv = (ILockBytes *)this; else if (IID_CBodyLockBytes == riid) *ppv = (CBodyLockBytes *)this; else { *ppv = NULL; return TrapError(E_NOINTERFACE); } // AddRef It ((IUnknown *)*ppv)->AddRef(); // Done return S_OK; } // -------------------------------------------------------------------------------- // CBodyLockBytes::AddRef // -------------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBodyLockBytes::AddRef(void) { return (ULONG)InterlockedIncrement(&m_cRef); } // -------------------------------------------------------------------------------- // CBodyLockBytes::Release // -------------------------------------------------------------------------------- STDMETHODIMP_(ULONG) CBodyLockBytes::Release(void) { LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return (ULONG)cRef; } // -------------------------------------------------------------------------------- // CBodyLockBytes::ReadAt // -------------------------------------------------------------------------------- #ifndef WIN16 STDMETHODIMP CBodyLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead) #else STDMETHODIMP CBodyLockBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP *pv, ULONG cb, ULONG *pcbRead) #endif // !WIN16 { // Locals HRESULT hr=S_OK; ULONG cbGet; ULONG cbRead; ULARGE_INTEGER uliActualOffset; // Thread Safety EnterCriticalSection(&m_cs); // Reading from ILockBytes... Assert(m_pLockBytes); #ifdef MAC // Compute Actual offset AssertSz(m_uliBodyStart.HighPart >= 0, "How can the start be negative??"); ULISet32(uliActualOffset, m_uliBodyStart.LowPart); AssertSz((uliActualOffset.LowPart + ulOffset.LowPart) >= uliActualOffset.LowPart, "Oops! We don't handle backwards reads correctly!"); uliActualOffset.LowPart += ulOffset.LowPart; // Compute amount to read cbGet = min(cb, m_uliBodyEnd.LowPart - uliActualOffset.LowPart); #else // !MAC // Compute Actual offset uliActualOffset.QuadPart = ulOffset.QuadPart + m_uliBodyStart.QuadPart; // Compute amount to read cbGet = (ULONG)min(cb, m_uliBodyEnd.QuadPart - uliActualOffset.QuadPart); #endif // MAC // Read a block of data... CHECKHR(hr = m_pLockBytes->ReadAt(uliActualOffset, pv, cbGet, &cbRead)); // Return amount read if (pcbRead) *pcbRead = cbRead; // E_PENDING if (0 == cbRead && BINDSTATE_COMPLETE != m_bindstate) { hr = TrapError(E_PENDING); goto exit; } exit: // Thread Safety LeaveCriticalSection(&m_cs); // Done return hr; } // -------------------------------------------------------------------------------- // CBodyLockBytes::Stat // -------------------------------------------------------------------------------- STDMETHODIMP CBodyLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag) { // Parameters if (NULL == pstatstg) return TrapError(E_INVALIDARG); // Thread Safety EnterCriticalSection(&m_cs); // Init ZeroMemory(pstatstg, sizeof(STATSTG)); // Reading from ILockBytes... pstatstg->type = STGTY_LOCKBYTES; // Set Size #ifdef MAC AssertSz(0 == m_uliBodyEnd.HighPart, "We have too big of a file!"); AssertSz(0 == m_uliBodyStart.HighPart, "We have too big of a file!"); ULISet32(pstatstg->cbSize, (m_uliBodyEnd.LowPart - m_uliBodyStart.LowPart)); #else // !MAC pstatstg->cbSize.QuadPart = m_uliBodyEnd.QuadPart - m_uliBodyStart.QuadPart; #endif // MAC // Thread Safety LeaveCriticalSection(&m_cs); // Done return S_OK; } // -------------------------------------------------------------------------------- // CBodyLockBytes::HrHandsOffStorage // -------------------------------------------------------------------------------- HRESULT CBodyLockBytes::HrHandsOffStorage(void) { // Locals HRESULT hr=S_OK; IStream *pstmTemp=NULL; ULARGE_INTEGER uliCopy; BYTE rgbBuffer[4096]; ULONG cbRead; // Thread Safety EnterCriticalSection(&m_cs); // If I live in the tree, copy data to temporary location... if (ISFLAGSET(m_dwState, BODYLOCK_HANDSONSTORAGE) && BINDSTATE_COMPLETE == m_bindstate) { // If more than one reference count if (m_cRef > 1) { // Create Temp Stream CHECKHR(hr = CreateTempFileStream(&pstmTemp)); // Set offset #ifdef MAC ULISet32(uliCopy, 0); #else // !MAC uliCopy.QuadPart = 0; #endif // MAC // Copy m_pLockBytes to pstmTemp while(1) { // Read CHECKHR(hr = ReadAt(uliCopy, rgbBuffer, sizeof(rgbBuffer), &cbRead)); // Done if (0 == cbRead) break; // Write to stream CHECKHR(hr = pstmTemp->Write(rgbBuffer, cbRead, NULL)); // Increment offset #ifdef MAC uliCopy.LowPart += cbRead; #else // !MAC uliCopy.QuadPart += cbRead; #endif // MAC } // Kill offsets, but maintain bodyend for stat command and Size esitmates #ifdef MAC AssertSz(0 == m_uliBodyEnd.HighPart, "We have too big of a file!"); m_uliBodyEnd.LowPart -= m_uliBodyStart.LowPart; ULISet32(m_uliBodyStart, 0); #else // !MAC m_uliBodyEnd.QuadPart -= m_uliBodyStart.QuadPart; m_uliBodyStart.QuadPart = 0; #endif // MAC // Rewind and commit CHECKHR(hr = pstmTemp->Commit(STGC_DEFAULT)); // Release current lockbytes SafeRelease(m_pLockBytes); // New CBodyLockBytes CHECKALLOC(m_pLockBytes = new CStreamLockBytes(pstmTemp)); } // Remove lives in tree flag FLAGCLEAR(m_dwState, BODYLOCK_HANDSONSTORAGE); } exit: // Cleanup SafeRelease(pstmTemp); // Thread Safety LeaveCriticalSection(&m_cs); // Done return hr; } // -------------------------------------------------------------------------------- // CBodyLockBytes::OnDataAvailable // -------------------------------------------------------------------------------- void CBodyLockBytes::OnDataAvailable(LPTREENODEINFO pNode) { // Thread Safety EnterCriticalSection(&m_cs); // Bind Complete m_bindstate = pNode->bindstate; // Save body start and body end.. #ifdef MAC Assert(m_uliBodyStart.LowPart <= pNode->cbBodyEnd); // Save start and End ULISet32(m_uliBodyEnd, pNode->cbBodyEnd); #else // !MAC Assert(m_uliBodyStart.QuadPart <= pNode->cbBodyEnd); // Save start and End m_uliBodyEnd.QuadPart = pNode->cbBodyEnd; #endif // MAC // Thread Safety LeaveCriticalSection(&m_cs); }