Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
c72ecb1d
Commit
c72ecb1d
authored
Jun 02, 2011
by
Vincent Povirk
Committed by
Alexandre Julliard
Jun 03, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ole32: Avoid opening source storage in IStorage::CopyTo.
parent
e11e1841
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
157 additions
and
124 deletions
+157
-124
storage32.c
dlls/ole32/storage32.c
+156
-123
storage32.c
dlls/ole32/tests/storage32.c
+1
-1
No files found.
dlls/ole32/storage32.c
View file @
c72ecb1d
...
...
@@ -87,6 +87,9 @@ struct StorageInternalImpl
};
typedef
struct
StorageInternalImpl
StorageInternalImpl
;
static
const
IStorageVtbl
TransactedSnapshotImpl_Vtbl
;
static
const
IStorageVtbl
Storage32InternalImpl_Vtbl
;
/* Method definitions for the Storage32InternalImpl class. */
static
StorageInternalImpl
*
StorageInternalImpl_Construct
(
StorageBaseImpl
*
parentStorage
,
DWORD
openFlags
,
DirRef
storageDirEntry
);
...
...
@@ -1600,163 +1603,88 @@ static HRESULT findTreeParent(StorageBaseImpl *storage, DirRef storageEntry,
}
/*************************************************************************
* CopyTo (IStorage)
*/
static
HRESULT
WINAPI
StorageBaseImpl_CopyTo
(
IStorage
*
iface
,
DWORD
ciidExclude
,
/* [in] */
const
IID
*
rgiidExclude
,
/* [size_is][unique][in] */
SNB
snbExclude
,
/* [unique][in] */
IStorage
*
pstgDest
)
/* [unique][in] */
{
StorageBaseImpl
*
const
This
=
(
StorageBaseImpl
*
)
iface
;
static
HRESULT
StorageBaseImpl_CopyStorageEntryTo
(
StorageBaseImpl
*
This
,
DirRef
srcEntry
,
BOOL
skip_storage
,
BOOL
skip_stream
,
SNB
snbExclude
,
IStorage
*
pstgDest
);
IEnumSTATSTG
*
elements
=
0
;
STATSTG
curElement
,
strStat
;
HRESULT
hr
;
IStorage
*
pstgTmp
,
*
pstgChild
;
IStream
*
pstrTmp
,
*
pstrChild
;
DirRef
srcEntryRef
;
DirEntry
srcEntry
;
BOOL
skip
=
FALSE
,
skip_storage
=
FALSE
,
skip_stream
=
FALSE
;
int
i
;
TRACE
(
"(%p, %d, %p, %p, %p)
\n
"
,
iface
,
ciidExclude
,
rgiidExclude
,
snbExclude
,
pstgDest
);
static
HRESULT
StorageBaseImpl_CopyChildEntryTo
(
StorageBaseImpl
*
This
,
DirRef
srcEntry
,
BOOL
skip_storage
,
BOOL
skip_stream
,
SNB
snbExclude
,
IStorage
*
pstgDest
)
{
DirEntry
data
;
HRESULT
hr
;
BOOL
skip
=
FALSE
;
IStorage
*
pstgTmp
;
IStream
*
pstrChild
,
*
pstrTmp
;
STATSTG
strStat
;
if
(
pstgDest
==
0
)
return
S
TG_E_INVALIDPOINTER
;
if
(
srcEntry
==
DIRENTRY_NULL
)
return
S
_OK
;
/*
* Enumerate the elements
*/
hr
=
IStorage_EnumElements
(
iface
,
0
,
0
,
0
,
&
elements
);
hr
=
StorageBaseImpl_ReadDirEntry
(
This
,
srcEntry
,
&
data
);
if
(
hr
!=
S_OK
)
if
(
FAILED
(
hr
)
)
return
hr
;
/*
* set the class ID
*/
IStorage_Stat
(
iface
,
&
curElement
,
STATFLAG_NONAME
);
IStorage_SetClass
(
pstgDest
,
&
curElement
.
clsid
);
for
(
i
=
0
;
i
<
ciidExclude
;
++
i
)
if
(
snbExclude
)
{
if
(
IsEqualGUID
(
&
IID_IStorage
,
&
rgiidExclude
[
i
]))
skip_storage
=
TRUE
;
else
if
(
IsEqualGUID
(
&
IID_IStream
,
&
rgiidExclude
[
i
]))
skip_stream
=
TRUE
;
else
WARN
(
"Unknown excluded GUID: %s
\n
"
,
debugstr_guid
(
&
rgiidExclude
[
i
]));
}
do
{
/*
* Obtain the next element
*/
hr
=
IEnumSTATSTG_Next
(
elements
,
1
,
&
curElement
,
NULL
);
WCHAR
**
snb
=
snbExclude
;
if
(
hr
==
S_FALSE
)
while
(
*
snb
!=
NULL
&&
!
skip
)
{
hr
=
S_OK
;
/* done, every element has been copied */
break
;
if
(
lstrcmpW
(
data
.
name
,
*
snb
)
==
0
)
skip
=
TRUE
;
++
snb
;
}
}
if
(
snbExclude
)
{
WCHAR
**
snb
=
snbExclude
;
skip
=
FALSE
;
while
(
*
snb
!=
NULL
&&
!
skip
)
{
if
(
lstrcmpW
(
curElement
.
pwcsName
,
*
snb
)
==
0
)
skip
=
TRUE
;
++
snb
;
}
}
if
(
skip
)
goto
cleanup
;
if
(
curElement
.
type
==
STGTY_STORAGE
)
if
(
!
skip
)
{
if
(
data
.
stgType
==
STGTY_STORAGE
&&
!
skip_storage
)
{
if
(
skip_storage
)
goto
cleanup
;
/*
* open child source storage
*/
hr
=
IStorage_OpenStorage
(
iface
,
curElement
.
pwcsName
,
NULL
,
STGM_READ
|
STGM_SHARE_EXCLUSIVE
,
NULL
,
0
,
&
pstgChild
);
if
(
hr
!=
S_OK
)
goto
cleanup
;
/*
* create a new storage in destination storage
*/
hr
=
IStorage_CreateStorage
(
pstgDest
,
curElement
.
pwcsN
ame
,
hr
=
IStorage_CreateStorage
(
pstgDest
,
data
.
n
ame
,
STGM_FAILIFTHERE
|
STGM_WRITE
|
STGM_SHARE_EXCLUSIVE
,
0
,
0
,
0
,
0
,
&
pstgTmp
);
/*
* if it already exist, don't create a new one use this one
*/
if
(
hr
==
STG_E_FILEALREADYEXISTS
)
{
hr
=
IStorage_OpenStorage
(
pstgDest
,
curElement
.
pwcsN
ame
,
NULL
,
hr
=
IStorage_OpenStorage
(
pstgDest
,
data
.
n
ame
,
NULL
,
STGM_WRITE
|
STGM_SHARE_EXCLUSIVE
,
NULL
,
0
,
&
pstgTmp
);
}
if
(
hr
==
S_OK
)
if
(
SUCCEEDED
(
hr
)
)
{
/*
* do the copy recursively
*/
hr
=
IStorage_CopyTo
(
pstgChild
,
ciidExclude
,
rgiidExclude
,
NULL
,
pstgTmp
);
hr
=
StorageBaseImpl_CopyStorageEntryTo
(
This
,
srcEntry
,
skip_storage
,
skip_stream
,
NULL
,
pstgTmp
);
IStorage_Release
(
pstgTmp
);
IStorage_Release
(
pstgTmp
);
}
IStorage_Release
(
pstgChild
);
}
else
if
(
curElement
.
type
==
STGTY_STREAM
)
else
if
(
data
.
stgType
==
STGTY_STREAM
&&
!
skip_stream
)
{
if
(
skip_stream
)
goto
cleanup
;
/*
* create a new stream in destination storage. If the stream already
* exist, it will be deleted and a new one will be created.
*/
hr
=
IStorage_CreateStream
(
pstgDest
,
curElement
.
pwcsN
ame
,
hr
=
IStorage_CreateStream
(
pstgDest
,
data
.
n
ame
,
STGM_CREATE
|
STGM_WRITE
|
STGM_SHARE_EXCLUSIVE
,
0
,
0
,
&
pstrTmp
);
if
(
hr
!=
S_OK
)
goto
cleanup
;
/*
* open child stream storage. This operation must succeed even if the
* stream is already open, so we use internal functions to do it.
*/
srcEntryRef
=
findElement
(
This
,
This
->
storageDirEntry
,
curElement
.
pwcsName
,
&
srcEntry
);
if
(
!
srcEntryRef
)
{
ERR
(
"source stream not found
\n
"
);
hr
=
STG_E_DOCFILECORRUPT
;
}
if
(
hr
==
S_OK
)
{
pstrChild
=
(
IStream
*
)
StgStreamImpl_Construct
(
This
,
STGM_READ
|
STGM_SHARE_EXCLUSIVE
,
srcEntry
Ref
);
pstrChild
=
(
IStream
*
)
StgStreamImpl_Construct
(
This
,
STGM_READ
|
STGM_SHARE_EXCLUSIVE
,
srcEntry
);
if
(
pstrChild
)
IStream_AddRef
(
pstrChild
);
else
...
...
@@ -1786,21 +1714,126 @@ static HRESULT WINAPI StorageBaseImpl_CopyTo(
IStream_Release
(
pstrTmp
);
}
}
/* copy siblings */
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_CopyChildEntryTo
(
This
,
data
.
leftChild
,
skip_storage
,
skip_stream
,
snbExclude
,
pstgDest
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_CopyChildEntryTo
(
This
,
data
.
rightChild
,
skip_storage
,
skip_stream
,
snbExclude
,
pstgDest
);
return
hr
;
}
static
HRESULT
StorageBaseImpl_CopyStorageEntryTo
(
StorageBaseImpl
*
This
,
DirRef
srcEntry
,
BOOL
skip_storage
,
BOOL
skip_stream
,
SNB
snbExclude
,
IStorage
*
pstgDest
)
{
DirEntry
data
;
HRESULT
hr
;
hr
=
StorageBaseImpl_ReadDirEntry
(
This
,
srcEntry
,
&
data
);
if
(
SUCCEEDED
(
hr
))
hr
=
IStorage_SetClass
(
pstgDest
,
&
data
.
clsid
);
if
(
SUCCEEDED
(
hr
))
hr
=
StorageBaseImpl_CopyChildEntryTo
(
This
,
data
.
dirRootEntry
,
skip_storage
,
skip_stream
,
snbExclude
,
pstgDest
);
return
hr
;
}
/*************************************************************************
* CopyTo (IStorage)
*/
static
HRESULT
WINAPI
StorageBaseImpl_CopyTo
(
IStorage
*
iface
,
DWORD
ciidExclude
,
/* [in] */
const
IID
*
rgiidExclude
,
/* [size_is][unique][in] */
SNB
snbExclude
,
/* [unique][in] */
IStorage
*
pstgDest
)
/* [unique][in] */
{
StorageBaseImpl
*
const
This
=
(
StorageBaseImpl
*
)
iface
;
BOOL
skip_storage
=
FALSE
,
skip_stream
=
FALSE
;
int
i
;
TRACE
(
"(%p, %d, %p, %p, %p)
\n
"
,
iface
,
ciidExclude
,
rgiidExclude
,
snbExclude
,
pstgDest
);
if
(
pstgDest
==
0
)
return
STG_E_INVALIDPOINTER
;
for
(
i
=
0
;
i
<
ciidExclude
;
++
i
)
{
if
(
IsEqualGUID
(
&
IID_IStorage
,
&
rgiidExclude
[
i
]))
skip_storage
=
TRUE
;
else
if
(
IsEqualGUID
(
&
IID_IStream
,
&
rgiidExclude
[
i
]))
skip_stream
=
TRUE
;
else
{
WARN
(
"unknown element type: %d
\n
"
,
curElement
.
type
);
WARN
(
"Unknown excluded GUID: %s
\n
"
,
debugstr_guid
(
&
rgiidExclude
[
i
]));
}
if
(
!
skip_storage
)
{
/* Give up early if it looks like this would be infinitely recursive.
* Oddly enough, this includes some cases that aren't really recursive, like
* copying to a transacted child. */
IStorage
*
pstgDestAncestor
=
pstgDest
;
IStorage
*
pstgDestAncestorChild
=
NULL
;
/* Go up the chain from the destination until we find the source storage. */
while
(
pstgDestAncestor
!=
iface
)
{
pstgDestAncestorChild
=
pstgDest
;
if
(
pstgDestAncestor
->
lpVtbl
==
&
TransactedSnapshotImpl_Vtbl
)
{
TransactedSnapshotImpl
*
impl
=
(
TransactedSnapshotImpl
*
)
pstgDestAncestor
;
pstgDestAncestor
=
(
IStorage
*
)
impl
->
transactedParent
;
}
else
if
(
pstgDestAncestor
->
lpVtbl
==
&
Storage32InternalImpl_Vtbl
)
{
StorageInternalImpl
*
impl
=
(
StorageInternalImpl
*
)
pstgDestAncestor
;
pstgDestAncestor
=
(
IStorage
*
)
impl
->
parentStorage
;
}
else
break
;
}
cleanup:
CoTaskMemFree
(
curElement
.
pwcsName
);
}
while
(
hr
==
S_OK
)
;
if
(
pstgDestAncestor
==
iface
)
{
BOOL
fail
=
TRUE
;
/*
* Clean-up
*/
IEnumSTATSTG_Release
(
elements
);
if
(
pstgDestAncestorChild
&&
snbExclude
)
{
StorageBaseImpl
*
ancestorChildBase
=
(
StorageBaseImpl
*
)
pstgDestAncestorChild
;
DirEntry
data
;
WCHAR
**
snb
=
snbExclude
;
return
hr
;
StorageBaseImpl_ReadDirEntry
(
ancestorChildBase
,
ancestorChildBase
->
storageDirEntry
,
&
data
);
while
(
*
snb
!=
NULL
&&
fail
)
{
if
(
lstrcmpW
(
data
.
name
,
*
snb
)
==
0
)
fail
=
FALSE
;
++
snb
;
}
}
if
(
fail
)
return
STG_E_ACCESSDENIED
;
}
}
return
StorageBaseImpl_CopyStorageEntryTo
(
This
,
This
->
storageDirEntry
,
skip_storage
,
skip_stream
,
snbExclude
,
pstgDest
);
}
/*************************************************************************
...
...
dlls/ole32/tests/storage32.c
View file @
c72ecb1d
...
...
@@ -2881,7 +2881,7 @@ static void test_copyto_locking(void)
/* Try to copy the storage while the substorage is open */
r
=
IStorage_CopyTo
(
stg2
,
0
,
NULL
,
NULL
,
stg3
);
todo_wine
ok
(
r
==
S_OK
,
"IStorage->CopyTo failed, hr=%08x
\n
"
,
r
);
ok
(
r
==
S_OK
,
"IStorage->CopyTo failed, hr=%08x
\n
"
,
r
);
IStorage_Release
(
stg4
);
IStorage_Release
(
stg3
);
...
...
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