Vincent Povirk : ole32: Fail to open storage files that are locked incorrectly.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Mar 11 10:00:42 CDT 2015
Module: wine
Branch: master
Commit: 0b7c05389b1c5068077775b50edf620bc3b69084
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0b7c05389b1c5068077775b50edf620bc3b69084
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Tue Mar 10 15:21:29 2015 -0500
ole32: Fail to open storage files that are locked incorrectly.
---
dlls/ole32/storage32.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index 64b3e13..8963044 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -2876,6 +2876,11 @@ static HRESULT StorageImpl_LockRegionSync(StorageImpl *This, ULARGE_INTEGER offs
HRESULT hr;
int delay = 0;
DWORD start_time = GetTickCount();
+ DWORD last_sanity_check = start_time;
+ ULARGE_INTEGER sanity_offset, sanity_cb;
+
+ sanity_offset.QuadPart = RANGELOCK_UNK1_FIRST;
+ sanity_cb.QuadPart = RANGELOCK_UNK1_LAST - RANGELOCK_UNK1_FIRST + 1;
do
{
@@ -2883,11 +2888,36 @@ static HRESULT StorageImpl_LockRegionSync(StorageImpl *This, ULARGE_INTEGER offs
if (hr == STG_E_ACCESSDENIED || hr == STG_E_LOCKVIOLATION)
{
- if (GetTickCount() - start_time >= 20000)
+ DWORD current_time = GetTickCount();
+ if (current_time - start_time >= 20000)
{
/* timeout */
break;
}
+ if (current_time - last_sanity_check >= 500)
+ {
+ /* Any storage implementation with the file open in a
+ * shared mode should not lock these bytes for writing. However,
+ * some programs (LibreOffice Writer) will keep ALL bytes locked
+ * when opening in exclusive mode. We can use a read lock to
+ * detect this case early, and not hang a full 20 seconds.
+ *
+ * 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);
+ 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);
+ hr = STG_E_ACCESSDENIED;
+ }
+ }
Sleep(delay);
if (delay < 150) delay++;
}
More information about the wine-cvs
mailing list