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
226363f5
Commit
226363f5
authored
Dec 04, 2009
by
Vincent Povirk
Committed by
Alexandre Julliard
Dec 11, 2009
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ole32: Implement transacted storage.
parent
d799f7e1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
198 additions
and
18 deletions
+198
-18
storage32.c
dlls/ole32/storage32.c
+196
-12
storage32.c
dlls/ole32/tests/storage32.c
+2
-6
No files found.
dlls/ole32/storage32.c
View file @
226363f5
...
...
@@ -126,6 +126,11 @@ typedef struct TransactedSnapshotImpl
struct
StorageBaseImpl
base
;
/*
* Changes are temporarily saved to the snapshot.
*/
StorageBaseImpl
*
snapshot
;
/*
* Changes are committed to the transacted parent.
*/
StorageBaseImpl
*
transactedParent
;
...
...
@@ -1288,6 +1293,46 @@ static HRESULT StorageImpl_DestroyDirEntry(
}
/***************************************************************************
*
* Internal Method
*
* Destroy an entry, its attached data, and all entries reachable from it.
*/
static
HRESULT
DestroyReachableEntries
(
StorageBaseImpl
*
base
,
DirRef
index
)
{
HRESULT
hr
=
S_OK
;
DirEntry
data
;
ULARGE_INTEGER
zero
;
zero
.
QuadPart
=
0
;
if
(
index
!=
DIRENTRY_NULL
)
{
hr
=
StorageBaseImpl_ReadDirEntry
(
base
,
index
,
&
data
);
if
(
SUCCEEDED
(
hr
))
hr
=
DestroyReachableEntries
(
base
,
data
.
dirRootEntry
);
if
(
SUCCEEDED
(
hr
))
hr
=
DestroyReachableEntries
(
base
,
data
.
leftChild
);
if
(
SUCCEEDED
(
hr
))
hr
=
DestroyReachableEntries
(
base
,
data
.
rightChild
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_StreamSetSize
(
base
,
index
,
zero
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_DestroyDirEntry
(
base
,
index
);
}
return
hr
;
}
/****************************************************************************
*
* Internal Method
...
...
@@ -3861,12 +3906,139 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
return
SmallBlockChainStream_Construct
(
This
,
NULL
,
streamEntryRef
);
}
static
HRESULT
CreateSnapshotFile
(
StorageBaseImpl
*
original
,
StorageBaseImpl
**
snapshot
)
{
HRESULT
hr
;
DirEntry
parentData
,
snapshotData
;
hr
=
StgCreateDocfile
(
NULL
,
STGM_READWRITE
|
STGM_SHARE_EXCLUSIVE
|
STGM_DELETEONRELEASE
,
0
,
(
IStorage
**
)
snapshot
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
StorageBaseImpl_ReadDirEntry
(
original
,
original
->
storageDirEntry
,
&
parentData
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_ReadDirEntry
((
*
snapshot
),
(
*
snapshot
)
->
storageDirEntry
,
&
snapshotData
);
if
(
SUCCEEDED
(
hr
))
{
memcpy
(
snapshotData
.
name
,
parentData
.
name
,
sizeof
(
snapshotData
.
name
));
snapshotData
.
sizeOfNameString
=
parentData
.
sizeOfNameString
;
snapshotData
.
stgType
=
parentData
.
stgType
;
snapshotData
.
clsid
=
parentData
.
clsid
;
snapshotData
.
ctime
=
parentData
.
ctime
;
snapshotData
.
mtime
=
parentData
.
mtime
;
hr
=
StorageBaseImpl_WriteDirEntry
((
*
snapshot
),
(
*
snapshot
)
->
storageDirEntry
,
&
snapshotData
);
}
if
(
SUCCEEDED
(
hr
))
hr
=
IStorage_CopyTo
((
IStorage
*
)
original
,
0
,
NULL
,
NULL
,
(
IStorage
*
)(
*
snapshot
));
if
(
FAILED
(
hr
))
IStorage_Release
((
IStorage
*
)(
*
snapshot
));
}
return
hr
;
}
static
HRESULT
WINAPI
TransactedSnapshotImpl_Commit
(
IStorage
*
iface
,
DWORD
grfCommitFlags
)
/* [in] */
{
FIXME
(
"(%p,%x): stub
\n
"
,
iface
,
grfCommitFlags
);
return
S_OK
;
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
iface
;
HRESULT
hr
;
DirEntry
data
,
tempStorageData
,
snapshotRootData
;
DirRef
tempStorageEntry
,
oldDirRoot
;
StorageInternalImpl
*
tempStorage
;
TRACE
(
"(%p,%x)
\n
"
,
iface
,
grfCommitFlags
);
/* Cannot commit a read-only transacted storage */
if
(
STGM_ACCESS_MODE
(
This
->
base
.
openFlags
)
==
STGM_READ
)
return
STG_E_ACCESSDENIED
;
/* To prevent data loss, we create the new structure in the file before we
* delete the old one, so that in case of errors the old data is intact. We
* shouldn't do this if STGC_OVERWRITE is set, but that flag should only be
* needed in the rare situation where we have just enough free disk space to
* overwrite the existing data. */
/* Create an orphaned storage in the parent for the new directory structure. */
memset
(
&
data
,
0
,
sizeof
(
data
));
data
.
name
[
0
]
=
'D'
;
data
.
sizeOfNameString
=
1
;
data
.
stgType
=
STGTY_STORAGE
;
data
.
leftChild
=
DIRENTRY_NULL
;
data
.
rightChild
=
DIRENTRY_NULL
;
data
.
dirRootEntry
=
DIRENTRY_NULL
;
hr
=
StorageBaseImpl_CreateDirEntry
(
This
->
transactedParent
,
&
data
,
&
tempStorageEntry
);
if
(
FAILED
(
hr
))
return
hr
;
tempStorage
=
StorageInternalImpl_Construct
(
This
->
transactedParent
,
STGM_READWRITE
|
STGM_SHARE_EXCLUSIVE
,
tempStorageEntry
);
if
(
tempStorage
)
{
hr
=
IStorage_CopyTo
((
IStorage
*
)
This
->
snapshot
,
0
,
NULL
,
NULL
,
(
IStorage
*
)
tempStorage
);
list_init
(
&
tempStorage
->
ParentListEntry
);
IStorage_Release
((
IStorage
*
)
tempStorage
);
}
else
hr
=
E_OUTOFMEMORY
;
if
(
FAILED
(
hr
))
{
DestroyReachableEntries
(
This
->
transactedParent
,
tempStorageEntry
);
return
hr
;
}
/* Update the storage to use the new data in one step. */
hr
=
StorageBaseImpl_ReadDirEntry
(
This
->
transactedParent
,
This
->
transactedParent
->
storageDirEntry
,
&
data
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
StorageBaseImpl_ReadDirEntry
(
This
->
transactedParent
,
tempStorageEntry
,
&
tempStorageData
);
}
if
(
SUCCEEDED
(
hr
))
{
hr
=
StorageBaseImpl_ReadDirEntry
(
This
->
snapshot
,
This
->
snapshot
->
storageDirEntry
,
&
snapshotRootData
);
}
if
(
SUCCEEDED
(
hr
))
{
oldDirRoot
=
data
.
dirRootEntry
;
data
.
dirRootEntry
=
tempStorageData
.
dirRootEntry
;
data
.
clsid
=
snapshotRootData
.
clsid
;
data
.
ctime
=
snapshotRootData
.
ctime
;
data
.
mtime
=
snapshotRootData
.
mtime
;
hr
=
StorageBaseImpl_WriteDirEntry
(
This
->
transactedParent
,
This
->
transactedParent
->
storageDirEntry
,
&
data
);
}
if
(
SUCCEEDED
(
hr
))
{
/* Destroy the old now-orphaned data. */
DestroyReachableEntries
(
This
->
transactedParent
,
oldDirRoot
);
StorageBaseImpl_DestroyDirEntry
(
This
->
transactedParent
,
tempStorageEntry
);
}
else
{
DestroyReachableEntries
(
This
->
transactedParent
,
tempStorageEntry
);
}
return
hr
;
}
static
HRESULT
WINAPI
TransactedSnapshotImpl_Revert
(
...
...
@@ -3896,6 +4068,8 @@ static void TransactedSnapshotImpl_Destroy( StorageBaseImpl *iface)
IStorage_Release
((
IStorage
*
)
This
->
transactedParent
);
IStorage_Release
((
IStorage
*
)
This
->
snapshot
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
...
...
@@ -3904,7 +4078,7 @@ static HRESULT TransactedSnapshotImpl_CreateDirEntry(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_CreateDirEntry
(
This
->
transactedParen
t
,
return
StorageBaseImpl_CreateDirEntry
(
This
->
snapsho
t
,
newData
,
index
);
}
...
...
@@ -3913,7 +4087,7 @@ static HRESULT TransactedSnapshotImpl_WriteDirEntry(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_WriteDirEntry
(
This
->
transactedParen
t
,
return
StorageBaseImpl_WriteDirEntry
(
This
->
snapsho
t
,
index
,
data
);
}
...
...
@@ -3922,7 +4096,7 @@ static HRESULT TransactedSnapshotImpl_ReadDirEntry(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_ReadDirEntry
(
This
->
transactedParen
t
,
return
StorageBaseImpl_ReadDirEntry
(
This
->
snapsho
t
,
index
,
data
);
}
...
...
@@ -3931,7 +4105,7 @@ static HRESULT TransactedSnapshotImpl_DestroyDirEntry(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_DestroyDirEntry
(
This
->
transactedParen
t
,
return
StorageBaseImpl_DestroyDirEntry
(
This
->
snapsho
t
,
index
);
}
...
...
@@ -3940,7 +4114,7 @@ static HRESULT TransactedSnapshotImpl_StreamReadAt(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_StreamReadAt
(
This
->
transactedParen
t
,
return
StorageBaseImpl_StreamReadAt
(
This
->
snapsho
t
,
index
,
offset
,
size
,
buffer
,
bytesRead
);
}
...
...
@@ -3949,7 +4123,7 @@ static HRESULT TransactedSnapshotImpl_StreamWriteAt(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_StreamWriteAt
(
This
->
transactedParen
t
,
return
StorageBaseImpl_StreamWriteAt
(
This
->
snapsho
t
,
index
,
offset
,
size
,
buffer
,
bytesWritten
);
}
...
...
@@ -3958,7 +4132,7 @@ static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base,
{
TransactedSnapshotImpl
*
This
=
(
TransactedSnapshotImpl
*
)
base
;
return
StorageBaseImpl_StreamSetSize
(
This
->
transactedParen
t
,
return
StorageBaseImpl_StreamSetSize
(
This
->
snapsho
t
,
index
,
newsize
);
}
...
...
@@ -4000,6 +4174,8 @@ static const StorageBaseImplVtbl TransactedSnapshotImpl_BaseVtbl =
static
HRESULT
TransactedSnapshotImpl_Construct
(
StorageBaseImpl
*
parentStorage
,
TransactedSnapshotImpl
**
result
)
{
HRESULT
hr
;
*
result
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
TransactedSnapshotImpl
));
if
(
*
result
)
{
...
...
@@ -4016,18 +4192,26 @@ static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage,
(
*
result
)
->
base
.
ref
=
1
;
(
*
result
)
->
base
.
storageDirEntry
=
parentStorage
->
storageDirEntry
;
(
*
result
)
->
base
.
openFlags
=
parentStorage
->
openFlags
;
(
*
result
)
->
base
.
filename
=
parentStorage
->
filename
;
/* Create a new temporary storage to act as the snapshot */
hr
=
CreateSnapshotFile
(
parentStorage
,
&
(
*
result
)
->
snapshot
);
if
(
SUCCEEDED
(
hr
))
{
(
*
result
)
->
base
.
storageDirEntry
=
(
*
result
)
->
snapshot
->
storageDirEntry
;
/* parentStorage already has 1 reference, which we take over here. */
(
*
result
)
->
transactedParent
=
parentStorage
;
parentStorage
->
transactedChild
=
(
StorageBaseImpl
*
)
*
result
;
}
return
S_OK
;
if
(
FAILED
(
hr
))
HeapFree
(
GetProcessHeap
(),
0
,
(
*
result
));
return
hr
;
}
else
return
E_OUTOFMEMORY
;
...
...
dlls/ole32/tests/storage32.c
View file @
226363f5
...
...
@@ -1003,17 +1003,13 @@ static void test_transact(void)
r
=
IStorage_OpenStorage
(
stg
,
stmname
,
NULL
,
STGM_TRANSACTED
|
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
NULL
,
0
,
&
stg2
);
ok
(
r
==
STG_E_FILENOTFOUND
,
"IStorage->OpenStream failed %08x
\n
"
,
r
);
todo_wine
{
r
=
IStorage_OpenStream
(
stg
,
stmname
,
NULL
,
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
0
,
&
stm
);
ok
(
r
==
STG_E_FILENOTFOUND
,
"IStorage->OpenStream should fail %08x
\n
"
,
r
);
}
if
(
r
==
S_OK
)
IStream_Release
(
stm
);
todo_wine
{
r
=
IStorage_OpenStorage
(
stg
,
stgname2
,
NULL
,
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
NULL
,
0
,
&
stg2
);
ok
(
r
==
STG_E_FILENOTFOUND
,
"IStorage->OpenStorage should fail %08x
\n
"
,
r
);
}
if
(
r
==
S_OK
)
IStorage_Release
(
stg2
);
...
...
@@ -1035,7 +1031,7 @@ static void test_transact(void)
IStorage_Release
(
stg3
);
r
=
IStorage_OpenStorage
(
stg2
,
stgname2
,
NULL
,
STGM_SHARE_EXCLUSIVE
|
STGM_READWRITE
,
NULL
,
0
,
&
stg3
);
todo_wine
ok
(
r
==
STG_E_FILENOTFOUND
,
"IStorage->OpenStorage should fail %08x
\n
"
,
r
);
ok
(
r
==
STG_E_FILENOTFOUND
,
"IStorage->OpenStorage should fail %08x
\n
"
,
r
);
if
(
r
==
S_OK
)
IStorage_Release
(
stg3
);
...
...
@@ -1423,7 +1419,7 @@ static void test_nonroot_transacted(void)
/* But changes cannot be committed. */
r
=
IStorage_Commit
(
stg2
,
0
);
todo_wine
ok
(
r
==
STG_E_ACCESSDENIED
,
"IStorage->Commit should fail, hr=%08x
\n
"
,
r
);
ok
(
r
==
STG_E_ACCESSDENIED
,
"IStorage->Commit should fail, hr=%08x
\n
"
,
r
);
IStorage_Release
(
stg2
);
}
...
...
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