ole32: Use grfLocksSupported to decide when LockRegion is implemented.
This commit is contained in:
parent
8ff3783586
commit
9cf835a947
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue