Commit 07e242f4 authored by Stephane Lussier's avatar Stephane Lussier Committed by Alexandre Julliard

Implementation of IStorage::CopyTo and IStream::CopyTo.

parent d1e2239f
......@@ -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;
}
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment