ole32: Use grfLocksSupported to decide when LockRegion is implemented.

This commit is contained in:
Vincent Povirk 2015-07-06 15:11:16 -05:00 committed by Alexandre Julliard
parent 8ff3783586
commit 9cf835a947
4 changed files with 88 additions and 28 deletions

View File

@ -386,6 +386,8 @@ static HRESULT WINAPI FileLockBytesImpl_Stat(ILockBytes* iface,
pstatstg->cbSize.u.LowPart = GetFileSize(This->hfile, &pstatstg->cbSize.u.HighPart);
/* FIXME: If the implementation is exported, we'll need to set other fields. */
pstatstg->grfLocksSupported = LOCK_EXCLUSIVE|LOCK_ONLYONCE|WINE_LOCK_READ;
return S_OK;
}

View File

@ -4822,9 +4822,31 @@ static HRESULT StorageImpl_SetTransactionSig(StorageBaseImpl *base,
return S_OK;
}
static HRESULT StorageImpl_LockRegion(StorageImpl *This, ULARGE_INTEGER offset,
ULARGE_INTEGER cb, DWORD dwLockType, BOOL *supported)
{
if ((dwLockType & This->locks_supported) == 0)
{
if (supported) *supported = FALSE;
return S_OK;
}
if (supported) *supported = TRUE;
return ILockBytes_LockRegion(This->lockBytes, offset, cb, dwLockType);
}
static HRESULT StorageImpl_UnlockRegion(StorageImpl *This, ULARGE_INTEGER offset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
if ((dwLockType & This->locks_supported) == 0)
return S_OK;
return ILockBytes_UnlockRegion(This->lockBytes, offset, cb, dwLockType);
}
/* Internal function */
static HRESULT StorageImpl_LockRegionSync(StorageImpl *This, ULARGE_INTEGER offset,
ULARGE_INTEGER cb, DWORD dwLockType)
ULARGE_INTEGER cb, DWORD dwLockType, BOOL *supported)
{
HRESULT hr;
int delay = 0;
@ -4837,7 +4859,7 @@ static HRESULT StorageImpl_LockRegionSync(StorageImpl *This, ULARGE_INTEGER offs
do
{
hr = ILockBytes_LockRegion(This->lockBytes, offset, cb, dwLockType);
hr = StorageImpl_LockRegion(This, offset, cb, dwLockType, supported);
if (hr == STG_E_ACCESSDENIED || hr == STG_E_LOCKVIOLATION)
{
@ -4857,17 +4879,12 @@ static HRESULT StorageImpl_LockRegionSync(StorageImpl *This, ULARGE_INTEGER offs
*
* This can collide with another attempt to open the file in
* exclusive mode, but it's unlikely, and someone would fail anyway. */
hr = ILockBytes_LockRegion(This->lockBytes, sanity_offset, sanity_cb, 0);
hr = StorageImpl_LockRegion(This, sanity_offset, sanity_cb, WINE_LOCK_READ, NULL);
if (hr == STG_E_ACCESSDENIED || hr == STG_E_LOCKVIOLATION)
break;
if (hr == STG_E_INVALIDFUNCTION)
{
/* ignore this, lockbytes might support dwLockType but not 0 */
hr = STG_E_ACCESSDENIED;
}
if (SUCCEEDED(hr))
{
ILockBytes_UnlockRegion(This->lockBytes, sanity_offset, sanity_cb, 0);
StorageImpl_UnlockRegion(This, sanity_offset, sanity_cb, WINE_LOCK_READ);
hr = STG_E_ACCESSDENIED;
}
@ -4900,10 +4917,7 @@ static HRESULT StorageImpl_LockTransaction(StorageBaseImpl *base, BOOL write)
cb.QuadPart = 1;
}
hr = StorageImpl_LockRegionSync(This, offset, cb, LOCK_ONLYONCE);
if (hr == STG_E_INVALIDFUNCTION)
hr = S_OK;
hr = StorageImpl_LockRegionSync(This, offset, cb, LOCK_ONLYONCE, NULL);
return hr;
}
@ -4925,10 +4939,7 @@ static HRESULT StorageImpl_UnlockTransaction(StorageBaseImpl *base, BOOL write)
cb.QuadPart = 1;
}
hr = ILockBytes_UnlockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
if (hr == STG_E_INVALIDFUNCTION)
hr = S_OK;
hr = StorageImpl_UnlockRegion(This, offset, cb, LOCK_ONLYONCE);
return hr;
}
@ -4955,10 +4966,10 @@ static HRESULT StorageImpl_CheckLockRange(StorageImpl *This, ULONG start,
offset.QuadPart = start;
cb.QuadPart = 1 + end - start;
hr = ILockBytes_LockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
if (SUCCEEDED(hr)) ILockBytes_UnlockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
hr = StorageImpl_LockRegion(This, offset, cb, LOCK_ONLYONCE, NULL);
if (SUCCEEDED(hr)) StorageImpl_UnlockRegion(This, offset, cb, LOCK_ONLYONCE);
if (hr == STG_E_ACCESSDENIED || hr == STG_E_LOCKVIOLATION)
if (FAILED(hr))
return fail_hr;
else
return S_OK;
@ -4975,7 +4986,7 @@ static HRESULT StorageImpl_LockOne(StorageImpl *This, ULONG start, ULONG end)
for (i=start; i<=end; i++)
{
offset.QuadPart = i;
hr = ILockBytes_LockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
hr = StorageImpl_LockRegion(This, offset, cb, LOCK_ONLYONCE, NULL);
if (hr != STG_E_ACCESSDENIED && hr != STG_E_LOCKVIOLATION)
break;
}
@ -5001,6 +5012,7 @@ static HRESULT StorageImpl_GrabLocks(StorageImpl *This, DWORD openFlags)
ULARGE_INTEGER offset;
ULARGE_INTEGER cb;
DWORD share_mode = STGM_SHARE_MODE(openFlags);
BOOL supported;
if (openFlags & STGM_NOSNAPSHOT)
{
@ -5012,10 +5024,10 @@ static HRESULT StorageImpl_GrabLocks(StorageImpl *This, DWORD openFlags)
/* Wrap all other locking inside a single lock so we can check ranges safely */
offset.QuadPart = RANGELOCK_CHECKLOCKS;
cb.QuadPart = 1;
hr = StorageImpl_LockRegionSync(This, offset, cb, LOCK_ONLYONCE);
hr = StorageImpl_LockRegionSync(This, offset, cb, LOCK_ONLYONCE, &supported);
/* If the ILockBytes doesn't support locking that's ok. */
if (hr == STG_E_INVALIDFUNCTION || hr == STG_E_UNIMPLEMENTEDFUNCTION) return S_OK;
if (!supported) return S_OK;
else if (FAILED(hr)) return hr;
hr = S_OK;
@ -5069,7 +5081,7 @@ static HRESULT StorageImpl_GrabLocks(StorageImpl *This, DWORD openFlags)
offset.QuadPart = RANGELOCK_CHECKLOCKS;
cb.QuadPart = 1;
ILockBytes_UnlockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
StorageImpl_UnlockRegion(This, offset, cb, LOCK_ONLYONCE);
return hr;
}
@ -5134,7 +5146,7 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
if (This->locked_bytes[i] != 0)
{
offset.QuadPart = This->locked_bytes[i];
ILockBytes_UnlockRegion(This->lockBytes, offset, cb, LOCK_ONLYONCE);
StorageImpl_UnlockRegion(This, offset, cb, LOCK_ONLYONCE);
}
}
@ -5201,7 +5213,8 @@ static HRESULT StorageImpl_Construct(
StorageImpl** result)
{
StorageImpl* This;
HRESULT hr = S_OK;
HRESULT hr = S_OK;
STATSTG stat;
if ( FAILED( validateSTGM(openFlags) ))
return STG_E_INVALIDFLAG;
@ -5247,7 +5260,17 @@ static HRESULT StorageImpl_Construct(
}
if (SUCCEEDED(hr))
hr = ILockBytes_Stat(This->lockBytes, &stat, STATFLAG_NONAME);
if (SUCCEEDED(hr))
{
This->locks_supported = stat.grfLocksSupported;
if (!hFile)
/* Don't try to use wine-internal locking flag with custom ILockBytes */
This->locks_supported &= ~WINE_LOCK_READ;
hr = StorageImpl_GrabLocks(This, openFlags);
}
if (SUCCEEDED(hr))
hr = StorageImpl_Refresh(This, TRUE, create);

View File

@ -411,6 +411,8 @@ struct StorageImpl
BlockChainStream* blockChainCache[BLOCKCHAIN_CACHE_SIZE];
UINT blockChainToEvict;
ULONG locks_supported;
ILockBytes* lockBytes;
ULONG locked_bytes[8];
@ -517,6 +519,9 @@ StgStreamImpl* StgStreamImpl_Construct(
#define RANGELOCK_FIRST RANGELOCK_UNK1_FIRST
#define RANGELOCK_LAST RANGELOCK_UNK2_LAST
/* internal value for LockRegion/UnlockRegion */
#define WINE_LOCK_READ 0x80000000
/******************************************************************************
* Endian conversion macros

View File

@ -63,6 +63,9 @@ typedef struct TestLockBytes {
BYTE* contents;
ULONG size;
ULONG buffer_size;
HRESULT lock_hr;
ULONG locks_supported;
ULONG lock_called;
} TestLockBytes;
static inline TestLockBytes *impl_from_ILockBytes(ILockBytes *iface)
@ -181,13 +184,16 @@ static HRESULT WINAPI TestLockBytes_SetSize(ILockBytes *iface,
static HRESULT WINAPI TestLockBytes_LockRegion(ILockBytes *iface,
ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
return S_OK;
TestLockBytes *This = impl_from_ILockBytes(iface);
This->lock_called++;
return This->lock_hr;
}
static HRESULT WINAPI TestLockBytes_UnlockRegion(ILockBytes *iface,
ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
return S_OK;
TestLockBytes *This = impl_from_ILockBytes(iface);
return This->lock_hr;
}
static HRESULT WINAPI TestLockBytes_Stat(ILockBytes *iface,
@ -209,6 +215,7 @@ static HRESULT WINAPI TestLockBytes_Stat(ILockBytes *iface,
pstatstg->type = STGTY_LOCKBYTES;
pstatstg->cbSize.QuadPart = This->size;
pstatstg->grfLocksSupported = This->locks_supported;
return S_OK;
}
@ -3855,6 +3862,29 @@ static void test_custom_lockbytes(void)
IStorage_Release(stg);
ok(!lockbytes->lock_called, "unexpected call to LockRegion\n");
lockbytes->locks_supported = LOCK_WRITE|LOCK_EXCLUSIVE|LOCK_ONLYONCE;
hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg);
ok(hr==S_OK, "StgCreateDocfileOnILockBytes failed %x\n", hr);
hr = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stm);
ok(hr==S_OK, "IStorage_CreateStream failed %x\n", hr);
IStream_Release(stm);
hr = IStorage_Commit(stg, 0);
IStorage_Release(stg);
ok(lockbytes->lock_called, "expected LockRegion to be called\n");
lockbytes->lock_hr = STG_E_INVALIDFUNCTION;
hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg);
ok(hr==STG_E_INVALIDFUNCTION, "StgCreateDocfileOnILockBytes failed %x\n", hr);
DeleteTestLockBytes(lockbytes);
}