windows-nt/Source/XPSP1/NT/com/ole32/stg/async/layout/laylkb.cxx

792 lines
19 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: laylkb.cxx
//
// Contents: File ILockBytes implementation for layout storage
//
// Classes:
//
// Functions:
//
// History: 19-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
#include "layouthd.cxx"
#pragma hdrstop
#include "laylkb.hxx"
#include <valid.h>
#include <dfver.h>
class CSafeCriticalSection
{
public:
inline CSafeCriticalSection(CRITICAL_SECTION *pcs);
inline ~CSafeCriticalSection();
private:
CRITICAL_SECTION *_pcs;
};
inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs)
{
_pcs = pcs;
EnterCriticalSection(_pcs);
}
inline CSafeCriticalSection::~CSafeCriticalSection()
{
LeaveCriticalSection(_pcs);
#if DBG == 1
_pcs = NULL;
#endif
}
#define TAKE_CS CSafeCriticalSection scs(&_cs);
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::CLayoutLockBytes, public
//
// Synopsis: Default constructor
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
CLayoutLockBytes::CLayoutLockBytes(void)
{
_cReferences = 1;
_h = INVALID_HANDLE_VALUE;
_hScript = INVALID_HANDLE_VALUE;
_fLogging = FALSE;
_cbSectorShift = 0;
_atcScriptName[0] = TEXT('\0');
_awcName[0] = L'\0';
_fCSInitialized = FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::~CLayoutLockBytes, public
//
// Synopsis: Destructor
//
// Returns: Appropriate status code
//
// History: 20-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
CLayoutLockBytes::~CLayoutLockBytes()
{
if (_h != INVALID_HANDLE_VALUE)
{
CloseHandle(_h);
_h = INVALID_HANDLE_VALUE;
}
if (_hScript != INVALID_HANDLE_VALUE)
{
CloseHandle(_hScript);
_hScript = INVALID_HANDLE_VALUE;
}
if (_fCSInitialized)
DeleteCriticalSection(&_cs);
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::Init, public
//
// Synopsis: Initialization function
//
// Arguments:
//
// Returns: Appropriate status code
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
SCODE CLayoutLockBytes::Init(OLECHAR const *pwcsName,
DWORD grfMode)
{
SCODE sc = S_OK;
BYTE abHeader[sizeof(CMSFHeaderData)];
ULONG cbRead;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Init:%p()\n", this));
if (pwcsName == NULL)
return STG_E_INVALIDNAME;
if (FALSE == _fCSInitialized)
{
__try
{
InitializeCriticalSection(&_cs);
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return HRESULT_FROM_WIN32( GetExceptionCode() );
}
_fCSInitialized = TRUE;
}
_grfMode = grfMode;
#ifndef UNICODE
TCHAR atcPath[MAX_PATH + 1];
UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
if (!WideCharToMultiByte(
uCodePage,
0,
pwcsName,
-1,
atcPath,
MAX_PATH + 1,
NULL,
NULL))
{
return STG_E_INVALIDNAME;
}
_h = CreateFileA(atcPath,
GENERIC_READ | GENERIC_WRITE, //Read-write
0, // No sharing
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL);
#else
_h = CreateFile(pwcsName,
GENERIC_READ | GENERIC_WRITE, //Read-write
0, // No sharing
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL);
#endif
if (_h == INVALID_HANDLE_VALUE)
{
layErr(Err, Win32ErrorToScode(GetLastError()));
}
lstrcpyW(_awcName, pwcsName);
//Get the sector size
boolChk(ReadFile(_h, abHeader, sizeof(CMSFHeaderData), &cbRead, NULL));
if (cbRead != sizeof(CMSFHeaderData))
{
return STG_E_READFAULT;
}
_cbSectorShift = ((CMSFHeaderData *)abHeader)->_uSectorShift;
if (((CMSFHeaderData*)abHeader)->_uDllVersion > rmjlarge)
return STG_E_OLDDLL;
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Init\n"));
Err:
return ResultFromScode(sc);
}
//+--------------------------------------------------------------
//
// Member: CLayoutLockBytes::QueryInterface, public
//
// Synopsis: Returns an object for the requested interface
//
// Arguments: [iid] - Interface ID
// [ppvObj] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppvObj]
//
// History: 26-Mar-92 DrewB Created
//
//---------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::QueryInterface(REFIID iid, void **ppvObj)
{
SCODE sc;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::QueryInterface(?, %p)\n",
ppvObj));
layChk(ValidateOutPtrBuffer(ppvObj));
*ppvObj = NULL;
sc = S_OK;
if (IsEqualIID(iid, IID_IUnknown))
{
*ppvObj = (IUnknown *)this;
CLayoutLockBytes::AddRef();
}
else if (IsEqualIID(iid, IID_ILockBytes))
{
*ppvObj = (ILockBytes *)this;
CLayoutLockBytes::AddRef();
}
else
{
sc = E_NOINTERFACE;
}
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::QueryInterface => %p\n",
ppvObj));
Err:
return ResultFromScode(sc);
}
//+--------------------------------------------------------------
//
// Member: CLayoutLockBytes::AddRef, public
//
// Synopsis: Increments the ref count
//
// Returns: Appropriate status code
//
// History: 16-Mar-92 DrewB Created
//
//---------------------------------------------------------------
STDMETHODIMP_(ULONG) CLayoutLockBytes::AddRef(void)
{
ULONG ulRet;
layDebugOut((DEB_TRACE, "In CLayoutLockBytes::AddRef()\n"));
InterlockedIncrement(&_cReferences);
ulRet = _cReferences;
layDebugOut((DEB_TRACE, "Out CLayoutLockBytes::AddRef\n"));
return ulRet;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::Release, public
//
// History: 20-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CLayoutLockBytes::Release(void)
{
LONG lRet;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Release:%p()\n", this));
lRet = InterlockedDecrement(&_cReferences);
if (lRet == 0)
{
delete this;
}
else if (lRet < 0)
{
lRet = 0;
}
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Release\n"));
return lRet;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::ReadAt, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
VOID HUGEP *pv,
ULONG cb,
ULONG *pcbRead)
{
CSafeCriticalSection scs(&_cs);
SCODE sc = S_OK;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::ReadAt:%p()\n", this));
ULONG ulLow = ulOffset.LowPart;
LONG lHigh = (LONG)ulOffset.HighPart;
if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
{
if (_hScript == INVALID_HANDLE_VALUE)
{
return STG_E_INVALIDHANDLE;
}
ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
(1 << _cbSectorShift))
>> _cbSectorShift);
ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
(1 << _cbSectorShift))
>> _cbSectorShift);
ULONG ulSect;
ULONG cbScriptWritten;
for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
{
layAssert(_hScript !=INVALID_HANDLE_VALUE);
boolChk(WriteFile(_hScript,
(VOID *)&ulSect,
sizeof(ULONG),
&cbScriptWritten,
NULL));
if (cbScriptWritten != sizeof(ULONG))
{
return STG_E_WRITEFAULT;
}
}
}
negChk(SetFilePointer(_h,
ulLow,
&lHigh,
FILE_BEGIN));
boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::ReadAt\n"));
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::WriteAt, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
VOID const HUGEP *pv,
ULONG cb,
ULONG *pcbWritten)
{
CSafeCriticalSection scs(&_cs);
SCODE sc = S_OK;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::WriteAt:%p()\n", this));
ULONG ulLow = ulOffset.LowPart;
LONG lHigh = (LONG)ulOffset.HighPart;
if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
{
if (_hScript == INVALID_HANDLE_VALUE)
{
return STG_E_INVALIDHANDLE;
}
ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
(1 << _cbSectorShift))
>> _cbSectorShift);
ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
(1 << _cbSectorShift))
>> _cbSectorShift);
ULONG ulSect;
ULONG cbScriptWritten;
for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
{
boolChk(WriteFile(_hScript,
(VOID *)&ulSect,
sizeof(ULONG),
&cbScriptWritten,
NULL));
if (cbScriptWritten != sizeof(ULONG))
{
return STG_E_WRITEFAULT;
}
}
}
negChk(SetFilePointer(_h,
ulLow,
&lHigh,
FILE_BEGIN));
boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::WriteAt\n"));
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::Flush, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::Flush(void)
{
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Flush:%p()\n", this));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Flush\n"));
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::SetSize, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::SetSize(ULARGE_INTEGER cb)
{
CSafeCriticalSection scs(&_cs);
SCODE sc = S_OK;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::SetSize:%p()\n", this));
LONG lHigh = (LONG)cb.HighPart;
ULONG ulLow = cb.LowPart;
negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
boolChk(SetEndOfFile(_h));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::SetSize\n"));
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::LockRegion, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::LockRegion(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
CSafeCriticalSection scs(&_cs);
SCODE sc = S_OK;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::LockRegion:%p()\n", this));
if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
{
return STG_E_INVALIDFUNCTION;
}
boolChk(LockFile(_h,
libOffset.LowPart,
libOffset.HighPart,
cb.LowPart,
cb.HighPart));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::LockRegion\n"));
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::UnlockRegion, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
CSafeCriticalSection scs(&_cs);
SCODE sc = S_OK;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::UnlockRegion:%p()\n", this));
if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
{
return STG_E_INVALIDFUNCTION;
}
boolChk(UnlockFile(_h,
libOffset.LowPart,
libOffset.HighPart,
cb.LowPart,
cb.HighPart));
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::UnlockRegion\n"));
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::Stat, public
//
// Synopsis:
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 20-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
{
CSafeCriticalSection scs(&_cs);
SCODE sc;
layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Stat:%p()\n", this));
negChk(pstatstg->cbSize.LowPart =
GetFileSize(_h, &pstatstg->cbSize.HighPart));
boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
&pstatstg->mtime));
pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
pstatstg->type = STGTY_LOCKBYTES;
pstatstg->grfMode = _grfMode;
pstatstg->pwcsName = NULL;
if ((grfStatFlag & STATFLAG_NONAME) == 0)
{
pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
(lstrlenW(_awcName) + 1) * sizeof(OLECHAR));
if (pstatstg->pwcsName == NULL)
return STG_E_INSUFFICIENTMEMORY;
lstrcpyW(pstatstg->pwcsName, _awcName);
}
sc = S_OK;
layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Stat\n"));
return NOERROR;
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::StartLogging, public
//
// Returns: Appropriate status code
//
// Modifies: _fLogging
//
// History: 24-Feb-96 SusiA Created
//
// Notes:
//
//----------------------------------------------------------------------------
SCODE CLayoutLockBytes::StartLogging(void)
{
CSafeCriticalSection scs(&_cs);
OLECHAR acTempPathName[MAX_PATH + 1];
SCODE sc = S_OK;
if (_fLogging)
{
return STG_E_INUSE; //logging already started!
}
if (_atcScriptName[0] != TEXT('\0'))
{
LONG dwDistanceToMoveHigh = 0;
//Script has already been started. Need to reopen it and seek
// to the end.
#ifndef UNICODE
_hScript = CreateFileA
#else
_hScript = CreateFile
#endif
(_atcScriptName,
GENERIC_WRITE, //Read-write
0, // No sharing
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL);
if (_hScript == INVALID_HANDLE_VALUE)
{
return LAST_STG_SCODE;
}
negChk(SetFilePointer(_hScript, 0, &dwDistanceToMoveHigh, FILE_END));
}
else
{
TCHAR atcPath[MAX_PATH + 1];
//Generate the script name, then create it.
boolChk(GetTempPath(MAX_PATH, atcPath));
boolChk(GetTempFileName(atcPath, TEXT("SCR"), 0, _atcScriptName));
//GetTempFileName actually creates the file, so we open with
// OPEN_EXISTING
#ifndef UNICODE
_hScript = CreateFileA
#else
_hScript = CreateFile
#endif
(_atcScriptName,
GENERIC_READ | GENERIC_WRITE, //Read-write
0, // No sharing
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL);
if (_hScript == INVALID_HANDLE_VALUE)
{
return LAST_STG_SCODE;
}
}
_fLogging = TRUE;
Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CLayoutLockBytes::StopLogging, public
//
// Returns: Appropriate status code
//
// Modifies: _fLogging
//
// History: 24-Feb-96 SusiA Created
//
// Notes:
//
//-----------------------------------------------------------------------------
SCODE CLayoutLockBytes::StopLogging(void)
{
SCODE sc = S_OK;
CSafeCriticalSection scs(&_cs);
if (!_fLogging)
{
return STG_E_UNKNOWN;
}
boolChk(CloseHandle(_hScript));
_hScript = INVALID_HANDLE_VALUE;
_fLogging = FALSE;
Err:
return sc;
}