Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
65887802
Commit
65887802
authored
Apr 18, 2014
by
Vincent Povirk
Committed by
Alexandre Julliard
Apr 29, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ole32: Initial storage file locking implementation.
parent
e6c58c74
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
207 additions
and
6 deletions
+207
-6
filelockbytes.c
dlls/ole32/filelockbytes.c
+36
-4
storage32.c
dlls/ole32/storage32.c
+167
-0
storage32.h
dlls/ole32/storage32.h
+2
-0
storage32.c
dlls/ole32/tests/storage32.c
+2
-2
No files found.
dlls/ole32/filelockbytes.c
View file @
65887802
...
@@ -334,15 +334,47 @@ static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGE
...
@@ -334,15 +334,47 @@ static HRESULT WINAPI FileLockBytesImpl_SetSize(ILockBytes* iface, ULARGE_INTEGE
static
HRESULT
WINAPI
FileLockBytesImpl_LockRegion
(
ILockBytes
*
iface
,
static
HRESULT
WINAPI
FileLockBytesImpl_LockRegion
(
ILockBytes
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
{
{
FIXME
(
"stub
\n
"
);
FileLockBytesImpl
*
This
=
impl_from_ILockBytes
(
iface
);
return
E_NOTIMPL
;
OVERLAPPED
ol
;
DWORD
lock_flags
=
LOCKFILE_FAIL_IMMEDIATELY
;
TRACE
(
"ofs %u count %u flags %x
\n
"
,
libOffset
.
u
.
LowPart
,
cb
.
u
.
LowPart
,
dwLockType
);
if
(
dwLockType
&
LOCK_WRITE
)
return
STG_E_INVALIDFUNCTION
;
if
(
dwLockType
&
(
LOCK_EXCLUSIVE
|
LOCK_ONLYONCE
))
lock_flags
|=
LOCKFILE_EXCLUSIVE_LOCK
;
ol
.
hEvent
=
0
;
ol
.
u
.
s
.
Offset
=
libOffset
.
u
.
LowPart
;
ol
.
u
.
s
.
OffsetHigh
=
libOffset
.
u
.
HighPart
;
if
(
LockFileEx
(
This
->
hfile
,
lock_flags
,
0
,
cb
.
u
.
LowPart
,
cb
.
u
.
HighPart
,
&
ol
))
return
S_OK
;
else
return
STG_E_ACCESSDENIED
;
}
}
static
HRESULT
WINAPI
FileLockBytesImpl_UnlockRegion
(
ILockBytes
*
iface
,
static
HRESULT
WINAPI
FileLockBytesImpl_UnlockRegion
(
ILockBytes
*
iface
,
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
ULARGE_INTEGER
libOffset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
{
{
FIXME
(
"stub
\n
"
);
FileLockBytesImpl
*
This
=
impl_from_ILockBytes
(
iface
);
return
E_NOTIMPL
;
OVERLAPPED
ol
;
TRACE
(
"ofs %u count %u flags %x
\n
"
,
libOffset
.
u
.
LowPart
,
cb
.
u
.
LowPart
,
dwLockType
);
if
(
dwLockType
&
LOCK_WRITE
)
return
STG_E_INVALIDFUNCTION
;
ol
.
hEvent
=
0
;
ol
.
u
.
s
.
Offset
=
libOffset
.
u
.
LowPart
;
ol
.
u
.
s
.
OffsetHigh
=
libOffset
.
u
.
HighPart
;
if
(
UnlockFileEx
(
This
->
hfile
,
0
,
cb
.
u
.
LowPart
,
cb
.
u
.
HighPart
,
&
ol
))
return
S_OK
;
else
return
STG_E_ACCESSDENIED
;
}
}
static
HRESULT
WINAPI
FileLockBytesImpl_Stat
(
ILockBytes
*
iface
,
static
HRESULT
WINAPI
FileLockBytesImpl_Stat
(
ILockBytes
*
iface
,
...
...
dlls/ole32/storage32.c
View file @
65887802
...
@@ -2743,6 +2743,157 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl =
...
@@ -2743,6 +2743,157 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl =
StorageImpl_StreamLink
StorageImpl_StreamLink
};
};
/* The storage format reserves the region from 0x7fffff00-0x7fffffff for
* locking and synchronization. Unfortuantely, the spec doesn't say which bytes
* within that range are used, and for what. Here's what I've been able to
* gather based on testing (ends of ranges may be wrong):
0x0 through 0x57: Unknown. Causes read-only exclusive opens to fail.
0x58 through 0x7f: Priority mode.
0x80: Commit lock.
0x81 through 0x91: Priority mode, again. Not sure why it uses two regions.
0x92: Lock-checking lock. Held while opening so ranges can be tested without
causing spurious failures if others try to grab or test those ranges at the
same time.
0x93 through 0xa6: Read mode.
0xa7 through 0xba: Write mode.
0xbb through 0xce: Deny read.
0xcf through 0xe2: Deny write.
0xe2 through 0xff: Unknown. Causes read-only exclusive opens to fail.
*/
static
HRESULT
StorageImpl_LockRegionSync
(
StorageImpl
*
This
,
ULARGE_INTEGER
offset
,
ULARGE_INTEGER
cb
,
DWORD
dwLockType
)
{
HRESULT
hr
;
/* potential optimization: if we have an HFILE use LockFileEx in blocking mode directly */
do
{
int
delay
=
0
;
hr
=
ILockBytes_LockRegion
(
This
->
lockBytes
,
offset
,
cb
,
dwLockType
);
if
(
hr
==
STG_E_ACCESSDENIED
)
{
Sleep
(
delay
);
if
(
delay
<
150
)
delay
++
;
}
}
while
(
hr
==
STG_E_ACCESSDENIED
);
return
hr
;
}
static
HRESULT
StorageImpl_CheckLockRange
(
StorageImpl
*
This
,
unsigned
char
start
,
unsigned
char
end
,
HRESULT
fail_hr
)
{
HRESULT
hr
;
ULARGE_INTEGER
offset
,
cb
;
offset
.
QuadPart
=
0x7fffff00
+
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
);
if
(
hr
==
STG_E_ACCESSDENIED
)
return
fail_hr
;
else
return
S_OK
;
}
static
HRESULT
StorageImpl_LockOne
(
StorageImpl
*
This
,
unsigned
char
start
,
unsigned
char
end
)
{
HRESULT
hr
=
S_OK
;
int
i
,
j
;
ULARGE_INTEGER
offset
,
cb
;
cb
.
QuadPart
=
1
;
for
(
i
=
start
;
i
<=
end
;
i
++
)
{
offset
.
QuadPart
=
0x7fffff00
+
i
;
hr
=
ILockBytes_LockRegion
(
This
->
lockBytes
,
offset
,
cb
,
LOCK_ONLYONCE
);
if
(
hr
!=
STG_E_ACCESSDENIED
)
break
;
}
if
(
SUCCEEDED
(
hr
))
{
for
(
j
=
0
;
j
<
sizeof
(
This
->
locked_bytes
)
/
sizeof
(
This
->
locked_bytes
[
0
]);
j
++
)
{
if
(
This
->
locked_bytes
[
j
]
==
0
)
{
This
->
locked_bytes
[
j
]
=
i
;
break
;
}
}
}
return
hr
;
}
static
HRESULT
StorageImpl_GrabLocks
(
StorageImpl
*
This
,
DWORD
openFlags
)
{
HRESULT
hr
;
ULARGE_INTEGER
offset
;
ULARGE_INTEGER
cb
;
DWORD
share_mode
=
STGM_SHARE_MODE
(
openFlags
);
/* Wrap all other locking inside a single lock so we can check ranges safely */
offset
.
QuadPart
=
0x7fffff92
;
cb
.
QuadPart
=
1
;
hr
=
StorageImpl_LockRegionSync
(
This
,
offset
,
cb
,
LOCK_ONLYONCE
);
/* If the ILockBytes doesn't support locking that's ok. */
if
(
FAILED
(
hr
))
return
S_OK
;
hr
=
S_OK
;
/* First check for any conflicting locks. */
if
(
SUCCEEDED
(
hr
)
&&
(
openFlags
&
STGM_PRIORITY
)
==
STGM_PRIORITY
)
hr
=
StorageImpl_CheckLockRange
(
This
,
0x80
,
0x80
,
STG_E_LOCKVIOLATION
);
if
(
SUCCEEDED
(
hr
)
&&
(
STGM_ACCESS_MODE
(
openFlags
)
!=
STGM_WRITE
))
hr
=
StorageImpl_CheckLockRange
(
This
,
0xbb
,
0xce
,
STG_E_SHAREVIOLATION
);
if
(
SUCCEEDED
(
hr
)
&&
(
STGM_ACCESS_MODE
(
openFlags
)
!=
STGM_READ
))
hr
=
StorageImpl_CheckLockRange
(
This
,
0xcf
,
0xe2
,
STG_E_SHAREVIOLATION
);
if
(
SUCCEEDED
(
hr
)
&&
(
share_mode
==
STGM_SHARE_DENY_READ
||
share_mode
==
STGM_SHARE_EXCLUSIVE
))
hr
=
StorageImpl_CheckLockRange
(
This
,
0x93
,
0xa6
,
STG_E_LOCKVIOLATION
);
if
(
SUCCEEDED
(
hr
)
&&
(
share_mode
==
STGM_SHARE_DENY_WRITE
||
share_mode
==
STGM_SHARE_EXCLUSIVE
))
hr
=
StorageImpl_CheckLockRange
(
This
,
0xa7
,
0xba
,
STG_E_LOCKVIOLATION
);
/* Then grab our locks. */
if
(
SUCCEEDED
(
hr
)
&&
(
openFlags
&
STGM_PRIORITY
)
==
STGM_PRIORITY
)
{
hr
=
StorageImpl_LockOne
(
This
,
0x58
,
0x7f
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageImpl_LockOne
(
This
,
0x81
,
0x91
);
}
if
(
SUCCEEDED
(
hr
)
&&
(
STGM_ACCESS_MODE
(
openFlags
)
!=
STGM_WRITE
))
hr
=
StorageImpl_LockOne
(
This
,
0x93
,
0xa6
);
if
(
SUCCEEDED
(
hr
)
&&
(
STGM_ACCESS_MODE
(
openFlags
)
!=
STGM_READ
))
hr
=
StorageImpl_LockOne
(
This
,
0xa7
,
0xba
);
if
(
SUCCEEDED
(
hr
)
&&
(
share_mode
==
STGM_SHARE_DENY_READ
||
share_mode
==
STGM_SHARE_EXCLUSIVE
))
hr
=
StorageImpl_LockOne
(
This
,
0xbb
,
0xce
);
if
(
SUCCEEDED
(
hr
)
&&
(
share_mode
==
STGM_SHARE_DENY_WRITE
||
share_mode
==
STGM_SHARE_EXCLUSIVE
))
hr
=
StorageImpl_LockOne
(
This
,
0xcf
,
0xe2
);
offset
.
QuadPart
=
0x7fffff92
;
cb
.
QuadPart
=
1
;
ILockBytes_UnlockRegion
(
This
->
lockBytes
,
offset
,
cb
,
LOCK_ONLYONCE
);
return
hr
;
}
static
HRESULT
StorageImpl_Construct
(
static
HRESULT
StorageImpl_Construct
(
HANDLE
hFile
,
HANDLE
hFile
,
LPCOLESTR
pwcsName
,
LPCOLESTR
pwcsName
,
...
@@ -2804,6 +2955,11 @@ static HRESULT StorageImpl_Construct(
...
@@ -2804,6 +2955,11 @@ static HRESULT StorageImpl_Construct(
if
(
FAILED
(
hr
))
if
(
FAILED
(
hr
))
goto
end
;
goto
end
;
hr
=
StorageImpl_GrabLocks
(
This
,
openFlags
);
if
(
FAILED
(
hr
))
goto
end
;
if
(
create
)
if
(
create
)
{
{
ULARGE_INTEGER
size
;
ULARGE_INTEGER
size
;
...
@@ -3038,6 +3194,17 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
...
@@ -3038,6 +3194,17 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
for
(
i
=
0
;
i
<
BLOCKCHAIN_CACHE_SIZE
;
i
++
)
for
(
i
=
0
;
i
<
BLOCKCHAIN_CACHE_SIZE
;
i
++
)
BlockChainStream_Destroy
(
This
->
blockChainCache
[
i
]);
BlockChainStream_Destroy
(
This
->
blockChainCache
[
i
]);
for
(
i
=
0
;
i
<
sizeof
(
This
->
locked_bytes
)
/
sizeof
(
This
->
locked_bytes
[
0
]);
i
++
)
{
ULARGE_INTEGER
offset
,
cb
;
cb
.
QuadPart
=
1
;
if
(
This
->
locked_bytes
[
i
]
!=
0
)
{
offset
.
QuadPart
=
0x7fffff00
+
This
->
locked_bytes
[
i
];
ILockBytes_UnlockRegion
(
This
->
lockBytes
,
offset
,
cb
,
LOCK_ONLYONCE
);
}
}
if
(
This
->
lockBytes
)
if
(
This
->
lockBytes
)
ILockBytes_Release
(
This
->
lockBytes
);
ILockBytes_Release
(
This
->
lockBytes
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
...
...
dlls/ole32/storage32.h
View file @
65887802
...
@@ -382,6 +382,8 @@ struct StorageImpl
...
@@ -382,6 +382,8 @@ struct StorageImpl
UINT
blockChainToEvict
;
UINT
blockChainToEvict
;
ILockBytes
*
lockBytes
;
ILockBytes
*
lockBytes
;
unsigned
char
locked_bytes
[
8
];
};
};
HRESULT
StorageImpl_ReadRawDirEntry
(
HRESULT
StorageImpl_ReadRawDirEntry
(
...
...
dlls/ole32/tests/storage32.c
View file @
65887802
...
@@ -3172,10 +3172,10 @@ static const int pr_fail_ranges[] = { 0x80,0x81, 0xbb,0xcf, -1 };
...
@@ -3172,10 +3172,10 @@ static const int pr_fail_ranges[] = { 0x80,0x81, 0xbb,0xcf, -1 };
static
const
int
roex_fail_ranges
[]
=
{
0x0
,
-
1
};
static
const
int
roex_fail_ranges
[]
=
{
0x0
,
-
1
};
static
const
struct
lock_test
lock_tests
[]
=
{
static
const
struct
lock_test
lock_tests
[]
=
{
{
STGM_PRIORITY
,
FALSE
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
priority_locked_bytes
,
pr_fail_ranges
,
TRU
E
},
{
STGM_PRIORITY
,
FALSE
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
priority_locked_bytes
,
pr_fail_ranges
,
FALS
E
},
{
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_READWRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
rw_locked_bytes
,
0
,
TRU
E
},
{
STGM_CREATE
|
STGM_READWRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
rw_locked_bytes
,
0
,
FALS
E
},
{
STGM_CREATE
|
STGM_READWRITE
|
STGM_SHARE_DENY_WRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwdw_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_READWRITE
|
STGM_SHARE_DENY_WRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwdw_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_WRITE
|
STGM_SHARE_DENY_WRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
wodw_locked_bytes
,
0
,
TRUE
},
{
STGM_CREATE
|
STGM_WRITE
|
STGM_SHARE_DENY_WRITE
|
STGM_TRANSACTED
,
TRUE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
wodw_locked_bytes
,
0
,
TRUE
},
{
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
FALSE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
rwex_fail_ranges
,
TRUE
},
{
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
FALSE
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
,
rwex_locked_bytes
,
rwex_fail_ranges
,
TRUE
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment