2020-09-30 17:12:29 +02:00

314 lines
10 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: lock.cxx
//
// Contents: Remote exclusion stuff for docfile
//
// Functions: GetAccess
// ReleaseAccess
// GetOpen
// ReleaseOpen
//
//--------------------------------------------------------------------------
#include <exphead.cxx>
#include <header.hxx>
#include <lock.hxx>
// Offset to next lock group from a particular group
#define OLOCKGROUP 1
//+--------------------------------------------------------------
//
// Function: GetAccess, public
//
// Synopsis: Takes appropriate access locks on an LStream
//
// Arguments: [plst] - LStream
// [df] - Permissions needed
// [poReturn] - Index of lock taken
//
// Returns: Appropriate status code
//
// Modifies: [poReturn]
//
//---------------------------------------------------------------
SCODE GetAccess(ILockBytes *plst, DFLAGS df, ULONG *poReturn)
{
SCODE sc;
ULARGE_INTEGER ulOffset, cbLength;
olDebugOut((DEB_ITRACE, "In GetAccess(%p, %X, %p)\n",
plst, df, poReturn));
*poReturn = NOLOCK;
ULISet32(ulOffset, OACCESS);
if (P_READ(df))
{
ULISet32(cbLength, 1);
olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
for (USHORT i = 0; i < CREADLOCKS; i++)
{
ULISetLow(ulOffset, OREADLOCK+i);
sc = DfGetScode(plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
if (SUCCEEDED(sc))
{
*poReturn = OREADLOCK + i;
break;
}
}
ULISetLow(ulOffset, OACCESS);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
if (i == CREADLOCKS)
olErr(EH_Err, STG_E_TOOMANYOPENFILES);
}
else if (P_WRITE(df))
{
olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
ULISet32(cbLength, 1 + CREADLOCKS);
olChk(DfGetScode(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)));
*poReturn = 0xFFFFFFFF;
}
olDebugOut((DEB_ITRACE, "Out GetAccess => %lu\n", *poReturn));
return S_OK;
EH_Err:
return sc;
}
//+--------------------------------------------------------------
//
// Function: ReleaseAccess, public
//
// Synopsis: Releases access locks
//
// Arguments: [plst] - LStream that is locked
// [df] - Permission to release
// [offset] - Offset of locks taken
//
//---------------------------------------------------------------
void ReleaseAccess(ILockBytes *plst, DFLAGS df, ULONG offset)
{
ULARGE_INTEGER ulOffset, cbLength;
olDebugOut((DEB_ITRACE, "In ReleaseAccess(%p, %lX, %lu)\n",
plst, df, offset));
if (offset == NOLOCK)
return;
if (P_READ(df))
{
ULISet32(ulOffset, offset);
ULISet32(cbLength, 1);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
else if (P_WRITE(df))
{
olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
ULISet32(ulOffset, OACCESS);
ULISet32(cbLength, 1 + CREADLOCKS);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
olDebugOut((DEB_ITRACE, "Out ReleaseAccess\n"));
}
//+--------------------------------------------------------------
//
// Function: GetOpen, public
//
// Synopsis: Gets locks on an LStream during opening
//
// Arguments: [plst] - LStream
// [df] - Permissions to take
// [fCheck] - Whether to check for existing locks or not
// [puReturn] - Index of lock taken
//
// Returns: Appropriate status code
//
// Modifies: [puReturn]
//
//---------------------------------------------------------------
SCODE GetOpen(ILockBytes *plst,
DFLAGS df,
BOOL fCheck,
ULONG *puReturn)
{
SCODE sc;
ULONG i;
ULARGE_INTEGER ulOffset, cbLength;
olDebugOut((DEB_ITRACE, "In GetOpen(%p, %lX, %d, %p)\n",
plst, df, fCheck, puReturn));
*puReturn = NOLOCK;
ULISet32(ulOffset, OUPDATE);
ULISet32(cbLength, 1);
olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
if (fCheck)
{
ULISetLow(cbLength, COPENLOCKS);
if (P_DENYREAD(df))
{
ULISetLow(ulOffset, OOPENREADLOCK);
olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (P_DENYWRITE(df))
{
ULISetLow(ulOffset, OOPENWRITELOCK);
olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (P_READ(df))
{
ULISetLow(ulOffset, OOPENDENYREADLOCK);
olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (P_WRITE(df))
{
ULISetLow(ulOffset, OOPENDENYWRITELOCK);
olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
}
ULISetLow(cbLength, 1);
for (i = 0; i < COPENLOCKS; i = i + OLOCKGROUP)
{
ULISetLow(ulOffset, OOPENREADLOCK+i);
olHChkTo(EH_Loop, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
ULISetLow(ulOffset, OOPENWRITELOCK+i);
olHChkTo(EH_UnlockR, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
olHChkTo(EH_UnlockW, plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE));
ULISetLow(ulOffset, OOPENDENYWRITELOCK+i);
if (SUCCEEDED(DfGetScode(plst->LockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))))
break;
ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
EH_UnlockW:
ULISetLow(ulOffset, OOPENWRITELOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
EH_UnlockR:
ULISetLow(ulOffset, OOPENREADLOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
EH_Loop:
;
}
if (i >= COPENLOCKS)
olErr(EH_UnlockUpdate, STG_E_TOOMANYOPENFILES);
if (!P_READ(df))
{
ULISetLow(ulOffset, OOPENREADLOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (!P_WRITE(df))
{
ULISetLow(ulOffset, OOPENWRITELOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (!P_DENYREAD(df))
{
ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
if (!P_DENYWRITE(df))
{
ULISetLow(ulOffset, OOPENDENYWRITELOCK+i);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
}
ULISetLow(ulOffset, OUPDATE);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
// 0 <= i < COPENLOCKS, but 0 is the invalid value, so increment
// on the way out
*puReturn = i + 1;
olDebugOut((DEB_ITRACE, "Out GetOpen => %lu\n", *puReturn));
return S_OK;
EH_UnlockUpdate:
ULISetLow(ulOffset, OUPDATE);
ULISetLow(cbLength, 1);
olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
EH_Err:
return sc;
}
//+--------------------------------------------------------------
//
// Function: ReleaseOpen, public
//
// Synopsis: Releases opening locks
//
// Arguments: [plst] - LStream
// [df] - Locks taken
// [offset] - Index of locks
//
// Requires: offset != NOLOCK
//
//---------------------------------------------------------------
void ReleaseOpen(ILockBytes *plst, DFLAGS df, ULONG offset)
{
ULARGE_INTEGER ulOffset, cbLength;
olDebugOut((DEB_ITRACE, "In ReleaseOpen(%p, %lX, %lu)\n",
plst, df, offset));
olAssert(offset != NOLOCK);
// we incremented at the end of GetOpen, so we decrement here
// to restore the proper lock index
offset--;
ULISetHigh(ulOffset, 0);
ULISet32(cbLength, 1);
if (P_READ(df))
{
ULISetLow(ulOffset, OOPENREADLOCK+offset);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
if (P_WRITE(df))
{
ULISetLow(ulOffset, OOPENWRITELOCK+offset);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
if (P_DENYREAD(df))
{
ULISetLow(ulOffset, OOPENDENYREADLOCK+offset);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
if (P_DENYWRITE(df))
{
ULISetLow(ulOffset, OOPENDENYWRITELOCK+offset);
olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
LOCK_ONLYONCE))) &&
aMsg("Non-fatal (Removable media?)"));
}
olDebugOut((DEB_ITRACE, "Out ReleaseOpen\n"));
}