You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
9.8 KiB
334 lines
9.8 KiB
// --------------------------------------------------------------------------------
|
|
// 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);
|
|
}
|