Implementation of IStorage::CopyTo and IStream::CopyTo.
This commit is contained in:
parent
d1e2239ff0
commit
07e242f4a3
|
@ -648,10 +648,10 @@ ICOM_DEFINE(IStream,ISequentialStream)
|
|||
/*** IStream32 methods ***/
|
||||
#define IStream_Seek(p,a,b,c) ICOM_CALL3(Seek,p,a,b,c)
|
||||
#define IStream_SetSize(p,a) ICOM_CALL1(SetSize,p,a)
|
||||
#define IStream_CopyTo(pa,b,c,d) ICOM_CALL4(CopyTo,pa,b,c,d)
|
||||
#define IStream_CopyTo(p,a,b,c,d) ICOM_CALL4(CopyTo,p,a,b,c,d)
|
||||
#define IStream_Commit(p,a) ICOM_CALL1(Commit,p,a)
|
||||
#define IStream_Revert(p) ICOM_CALL (Revert,p)
|
||||
#define IStream_LockRegion(pa,b,c) ICOM_CALL3(LockRegion,pa,b,c)
|
||||
#define IStream_LockRegion(p,a,b,c) ICOM_CALL3(LockRegion,p,a,b,c)
|
||||
#define IStream_UnlockRegion(p,a,b,c) ICOM_CALL3(UnlockRegion,p,a,b,c)
|
||||
#define IStream_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b)
|
||||
#define IStream_Clone(p,a) ICOM_CALL1(Clone,p,a)
|
||||
|
@ -668,10 +668,10 @@ ICOM_DEFINE(IStream,ISequentialStream)
|
|||
/*** IStream methods ***/
|
||||
#define IStream_Seek(p,a,b,c) ICOM_CALL3(Seek,p,a,b,c)
|
||||
#define IStream_SetSize(p,a) ICOM_CALL1(SetSize,p,a)
|
||||
#define IStream_CopyTo(pa,b,c,d) ICOM_CALL4(CopyTo,pa,b,c,d)
|
||||
#define IStream_CopyTo(p,a,b,c,d) ICOM_CALL4(CopyTo,p,a,b,c,d)
|
||||
#define IStream_Commit(p,a) ICOM_CALL1(Commit,p,a)
|
||||
#define IStream_Revert(p) ICOM_CALL (Revert,p)
|
||||
#define IStream_LockRegion(pa,b,c) ICOM_CALL3(LockRegion,pa,b,c)
|
||||
#define IStream_LockRegion(p,a,b,c) ICOM_CALL3(LockRegion,p,a,b,c)
|
||||
#define IStream_UnlockRegion(p,a,b,c) ICOM_CALL3(UnlockRegion,p,a,b,c)
|
||||
#define IStream_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b)
|
||||
#define IStream_Clone(p,a) ICOM_CALL1(Clone,p,a)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "debug.h"
|
||||
#include "wine/obj_storage.h"
|
||||
|
||||
#include "storage32.h"
|
||||
|
@ -627,6 +628,13 @@ HRESULT WINAPI StgStreamImpl_SetSize(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
/***
|
||||
* This method is part of the IStream interface.
|
||||
*
|
||||
* It will copy the 'cb' Bytes to 'pstm' IStream.
|
||||
*
|
||||
* See the documentation of IStream for more info.
|
||||
*/
|
||||
HRESULT WINAPI StgStreamImpl_CopyTo(
|
||||
IStream* iface,
|
||||
IStream* pstm, /* [unique][in] */
|
||||
|
@ -634,7 +642,69 @@ HRESULT WINAPI StgStreamImpl_CopyTo(
|
|||
ULARGE_INTEGER* pcbRead, /* [out] */
|
||||
ULARGE_INTEGER* pcbWritten) /* [out] */
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
StgStreamImpl* const This=(StgStreamImpl*)iface;
|
||||
HRESULT hr = S_OK;
|
||||
BYTE tmpBuffer[128];
|
||||
ULONG bytesRead, bytesWritten, copySize;
|
||||
ULARGE_INTEGER totalBytesRead;
|
||||
ULARGE_INTEGER totalBytesWritten;
|
||||
|
||||
/*
|
||||
* Sanity check
|
||||
*/
|
||||
if ( pstm == 0 )
|
||||
return STG_E_INVALIDPOINTER;
|
||||
|
||||
totalBytesRead.LowPart = totalBytesRead.HighPart = 0;
|
||||
totalBytesWritten.LowPart = totalBytesWritten.HighPart = 0;
|
||||
|
||||
/*
|
||||
* use stack to store data temporarly
|
||||
* there is surely more performant way of doing it, for now this basic
|
||||
* implementation will do the job
|
||||
*/
|
||||
while ( cb.LowPart > 0 )
|
||||
{
|
||||
if ( cb.LowPart >= 128 )
|
||||
copySize = 128;
|
||||
else
|
||||
copySize = cb.LowPart;
|
||||
|
||||
StgStreamImpl_Read(iface, tmpBuffer, 128, &bytesRead);
|
||||
|
||||
totalBytesRead.LowPart += bytesRead;
|
||||
|
||||
StgStreamImpl_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
|
||||
|
||||
totalBytesWritten.LowPart += bytesWritten;
|
||||
|
||||
/*
|
||||
* Check that read & write operations were succesfull
|
||||
*/
|
||||
if ( (bytesRead != copySize) && (bytesWritten != copySize) )
|
||||
{
|
||||
hr = STG_E_MEDIUMFULL;
|
||||
break;
|
||||
}
|
||||
|
||||
cb.LowPart = cb.LowPart - copySize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update number of bytes read and written
|
||||
*/
|
||||
if (pcbRead)
|
||||
{
|
||||
pcbRead->LowPart = totalBytesRead.LowPart;
|
||||
pcbRead->HighPart = totalBytesRead.HighPart;
|
||||
}
|
||||
|
||||
if (pcbWritten)
|
||||
{
|
||||
pcbWritten->LowPart = totalBytesWritten.LowPart;
|
||||
pcbWritten->HighPart = totalBytesWritten.HighPart;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -672,6 +742,7 @@ HRESULT WINAPI StgStreamImpl_LockRegion(
|
|||
ULARGE_INTEGER cb, /* [in] */
|
||||
DWORD dwLockType) /* [in] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -681,6 +752,7 @@ HRESULT WINAPI StgStreamImpl_UnlockRegion(
|
|||
ULARGE_INTEGER cb, /* [in] */
|
||||
DWORD dwLockType) /* [in] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -725,5 +797,6 @@ HRESULT WINAPI StgStreamImpl_Clone(
|
|||
IStream* iface,
|
||||
IStream** ppstm) /* [out] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
|
151
ole/storage32.c
151
ole/storage32.c
|
@ -901,6 +901,7 @@ HRESULT WINAPI StorageImpl_CreateStorage(
|
|||
ULONG newPropertyIndex;
|
||||
HRESULT hr;
|
||||
|
||||
|
||||
/*
|
||||
* Validate parameters
|
||||
*/
|
||||
|
@ -1012,6 +1013,7 @@ HRESULT WINAPI StorageImpl_CreateStorage(
|
|||
return hr;
|
||||
}
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1264,150 @@ HRESULT WINAPI StorageImpl_CopyTo(
|
|||
SNB snbExclude, /* [unique][in] */
|
||||
IStorage *pstgDest) /* [unique][in] */
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
IEnumSTATSTG *elements = 0;
|
||||
STATSTG curElement, strStat;
|
||||
HRESULT hr;
|
||||
IStorage *pstgTmp, *pstgChild;
|
||||
IStream *pstrTmp, *pstrChild;
|
||||
|
||||
if ((ciidExclude != 0) || (rgiidExclude != NULL) || (snbExclude != NULL))
|
||||
FIXME( ole, "Exclude option not implemented\n");
|
||||
|
||||
/*
|
||||
* Perform a sanity check
|
||||
*/
|
||||
if ( pstgDest == 0 )
|
||||
return STG_E_INVALIDPOINTER;
|
||||
|
||||
/*
|
||||
* Enumerate the elements
|
||||
*/
|
||||
hr = IStorage_EnumElements( iface, 0, 0, 0, &elements );
|
||||
|
||||
if ( hr != S_OK )
|
||||
return hr;
|
||||
|
||||
/*
|
||||
* set the class ID
|
||||
*/
|
||||
StorageBaseImpl_Stat( iface, &curElement, STATFLAG_NONAME);
|
||||
IStorage_SetClass( pstgDest, &curElement.clsid );
|
||||
|
||||
do
|
||||
{
|
||||
/*
|
||||
* Obtain the next element
|
||||
*/
|
||||
hr = IEnumSTATSTG_Next( elements, 1, &curElement, NULL );
|
||||
|
||||
if ( hr == S_FALSE )
|
||||
{
|
||||
hr = S_OK; /* done, every element has been copied */
|
||||
break;
|
||||
}
|
||||
|
||||
if (curElement.type == STGTY_STORAGE)
|
||||
{
|
||||
/*
|
||||
* open child source storage
|
||||
*/
|
||||
hr = StorageBaseImpl_OpenStorage( iface, curElement.pwcsName, NULL,
|
||||
STGM_READ|STGM_SHARE_EXCLUSIVE,
|
||||
NULL, 0, &pstgChild );
|
||||
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Check if destination storage is not a child of the source
|
||||
* storage, which will cause an infinite loop
|
||||
*/
|
||||
if (pstgChild == pstgDest)
|
||||
{
|
||||
IEnumSTATSTG_Release(elements);
|
||||
|
||||
return STG_E_ACCESSDENIED;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a new storage in destination storage
|
||||
*/
|
||||
hr = IStorage_CreateStorage( pstgDest, curElement.pwcsName,
|
||||
STGM_FAILIFTHERE|STGM_WRITE, 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.pwcsName, NULL,
|
||||
STGM_WRITE|STGM_SHARE_EXCLUSIVE,
|
||||
NULL, 0, &pstgTmp );
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* do the copy recursively
|
||||
*/
|
||||
hr = IStorage_CopyTo( pstgChild, ciidExclude, rgiidExclude,
|
||||
snbExclude, pstgTmp );
|
||||
|
||||
IStorage_Release( pstgTmp );
|
||||
IStorage_Release( pstgChild );
|
||||
}
|
||||
else if (curElement.type == STGTY_STREAM)
|
||||
{
|
||||
/*
|
||||
* 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.pwcsName,
|
||||
STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE,
|
||||
0, 0, &pstrTmp );
|
||||
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
/*
|
||||
* open child stream storage
|
||||
*/
|
||||
hr = StorageBaseImpl_OpenStream( iface, curElement.pwcsName, NULL,
|
||||
STGM_READ|STGM_SHARE_EXCLUSIVE,
|
||||
0, &pstrChild );
|
||||
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get the size of the stream
|
||||
*/
|
||||
IStream_Stat( pstrChild, &strStat, STATFLAG_NONAME );
|
||||
|
||||
/*
|
||||
* do the copy
|
||||
*/
|
||||
hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize,
|
||||
NULL, NULL );
|
||||
|
||||
IStream_Release( pstrTmp );
|
||||
IStream_Release( pstrChild );
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN(ole, "unknown element type: %ld\n", curElement.type);
|
||||
}
|
||||
|
||||
} while (hr == S_OK);
|
||||
|
||||
/*
|
||||
* Clean-up
|
||||
*/
|
||||
IEnumSTATSTG_Release(elements);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1275,6 +1420,7 @@ HRESULT WINAPI StorageImpl_MoveElementTo(
|
|||
const OLECHAR *pwcsNewName,/* [string][in] */
|
||||
DWORD grfFlags) /* [in] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1441,7 @@ HRESULT WINAPI StorageImpl_Commit(
|
|||
HRESULT WINAPI StorageImpl_Revert(
|
||||
IStorage* iface)
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -1811,6 +1958,7 @@ HRESULT WINAPI StorageImpl_SetElementTimes(
|
|||
const FILETIME *patime, /* [in] */
|
||||
const FILETIME *pmtime) /* [in] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -1822,6 +1970,7 @@ HRESULT WINAPI StorageImpl_SetStateBits(
|
|||
DWORD grfStateBits,/* [in] */
|
||||
DWORD grfMask) /* [in] */
|
||||
{
|
||||
FIXME(ole, "not implemented!\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue